一個最普通類型的簽名會看起來像
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)
要繞過p olymorphic類型簽名,還記得我們有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)
(的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
和其他所有的只是簡單的組合!
所以沒有類型簽名,GHC只是假設'g'必須是單形的? (爲什麼?只是一個簡化的假設?)...'g'的類型簽名聲明'g'在其參數中是多態的,並返回一個結果,其類型取決於參數的類型。如果你希望返回類型不是'ab'形式(例如,'g = id',或'g = fromIntegral'和一個類型約束),我想你需要設置一個類型族或使用'g'的fundep。 (?) – misterbee
@misterbee我認爲這是Hindley-Milner類型系統的限制,它是基於GHC的。如果沒有多態類型簽名,Haskell無法進行多態類型推斷,除非該變量使用'where'或'let'子句進行綁定。 –
@misterbee我想你是正確的使用類型家庭或fundep,雖然我不知道如何做(尚)。 –