一个最通用的类型签名看起来像
map_arg :: (forall b.b -> a b) -> (a b -> a c -> a d -> e) -> b -> c -> d -> e
map_arg g f a b c = f (g a) (g b) (g c)
对于你的情况,如果你选择不g
作为参数,你可以做
map_just f a b c = f (g a) (g b) (g c) where g = Just
xs <- map_just getAddrInfo hints addr port
或者你可以只给类型签名g
:
map_arg (g :: forall b.b -> a b) f a b c = f (g a) (g b) (g c)
要绕过多态类型签名,请记住我们有Control.Functor.Pointed
,以便您可以使用它:
map_arg :: Pointed p => (p a -> p b -> p c -> d) -> a -> b -> c -> d
map_arg f a b c = f (point a) (point b) (point c)
(for的实现Pointed
就是Maybe
你Just
想要的)
要获得通用版本,请注意
map1 :: Pointed p => (p a -> b) -> a -> b
map1 f = f . point
map2 :: Pointed p => (p a -> p b -> c) -> a -> b -> c
map2 f = map1 . map1 f
map3 :: Pointed p => (p a -> p b -> p c -> d) -> a -> b -> c -> d
map3 f = map2 . map1 f
看到了吗?你只需要map1
和所有其他的只是简单的组合!