2016-02-05 35 views
4

有什麼辦法可以將函數作爲參數傳遞給兩種不同的類型嗎?作爲一個人爲的例子,我可以創造與表達(Just 3, Just True)一個(Maybe Int, Maybe Bool),但如果我試圖讓這種行爲更通用與功能應用函數作爲參數傳遞給Haskell中的不同類型

generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool) 
generic f = (f 3, f True) 

,這樣我也許能像做generic Just,編譯器會抱怨因爲類型變量a是不變的。

此用例將通用函數應用於每個節點通過類型進行參數化的樹結構。

回答

9

這可以使用等級2多態性如下來實現:

{-# LANGUAGE Rank2Types #-} 
generic :: (forall a. a -> Maybe a) -> (Maybe Int, Maybe Bool) 
generic f = (f 3, f True) 

通常你會需要一些類型類的限制(沒有因爲generic要求執行,但因爲主叫方可以不通過參數的作品所有類型),例如

genericNum :: (forall a. Num a => a -> a) -> (Int, Integer) 
genericNum f = (f 3, f 9) 
+1

我不知道你對此有什麼看法,但我*總是*打開'ScopedTypeVariables'當我使用一個擴展,使'forall';否則我很可能會在路上感到困惑。 – dfeuer

+0

完美,非常感謝!你知道所有這些現代語言擴展的優秀資源嗎?我所能找到的所有Haskell書籍大部分都與Haskell 98和Haskell文檔相關,它們可能會讓你非常疲憊...... – igorbark

+0

@igorbark如果你想要所有的擴展,沒有比[馬的嘴巴]更好的源代碼(https:// downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghc-language-features.html)。 –

相關問題