2015-09-20 24 views
1

假設兩個新類型都是這樣在推斷爲FMAP ADT的

type MyProductType a = (FType1 a, FType2 a) 

type MyCoproductType a = Either (FType1 a) (FType2 a) 

定義......這FType1Ftype2Functor兩個實例。

如果現在要宣佈MyProductTypeMyCoproductTypeFunctor情況下,將編譯器需要各自fmap明確的定義,也可以推斷從以前的這些定義?

此外,這個問題的答案是實現相關的,還是從Haskell規範?


這種背景下,這個問題是由試圖作出發言的感something I'm reading動機。筆者首先界定

type Writer a = (a, String) 

...後來寫道(我的重點)

...的Writer類型構造是a函子。 我們甚至不需要執行fmap,因爲它只是一個簡單的產品類型。

強調的文字是我試圖理解的評論。我以爲這意味着,哈斯克爾可以根據函子類型推斷fmap的爲任何 ADT,並且,特別是,它可以推斷fmap一個‘簡單的產品類型’之類Writer,但現在我認爲這種解釋是不正確(至少如果我正確閱讀ØrjanJohansen的答案)。

至於作者所說的那句話,現在我真的沒有線索。也許他的意思是,以這樣一種方式重新定義Writer是不值得的,因爲它的功能性可以明確,因爲它是一個「簡單...類型」。 (救命稻草這裏抓。)

+2

你不能聲明他們'Functor',因爲已經有'(,)'和'Either'的實例。如果您使用'newtype',則可以使用['GeneralizedNewtypeDeriving'](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/deriving.html#newtype-deriving)推導實例。 –

+0

你可以使用'fmap fmap fmap'來映射內函數的函數。 – bheklilr

回答

6

首先,你一般不能定義新的實例爲type同義詞,尤其是部分不適用的,你需要在你的案件。我想你的意思是定義一個newtypedata代替:

newtype MyProductType a = MP (FType1 a, FType2 a) 
newtype MyCoproductType a = MC (Either (FType1 a) (FType2 a)) 

標準哈斯克爾隻字未提推導Functor自動可言,這是唯一可能與GHC的DeriveFunctor擴展。 (或者有時候GeneralizedNewtypeDeriving,但是這不適用於你的例子,因爲你沒有使用a作爲構造函數中的最後一個參數。)

所以讓我們嘗試:

{-# LANGUAGE DeriveFunctor #-} 
data FType1 a = FType1 a deriving Functor 
data FType2 a = FType2 a deriving Functor 
newtype MyProductType a = MP (FType1 a, FType2 a) deriving Functor 
newtype MyCoproductType a = MC (Either (FType1 a) (FType2 a)) deriving Functor 

我們得到的錯誤信息:

Test.hs:6:76: 
    Can't make a derived instance of ‘Functor MyCoproductType’: 
     Constructor ‘MC’ must use the type variable only as the last argument of a data type 
    In the newtype declaration for ‘MyCoproductType’ 

事實證明,GHC可以推導出第一三,但不是最後一個。我相信第三個只適用於元組,因爲元組是特殊的。 Either雖然不起作用,因爲GHC沒有保留任何關於如何處理第一個參數的特殊知識。它在名義上是數學函數在該論點中,但不是HaskellFunctor

請注意,GHC是聰明的使用變量只能作爲Functor s類型的最後一個參數。以下工作正常:

newtype MyWrappedType a = MW (Either (FType1 Int) (FType2 (Maybe a))) deriving Functor 

所以總結一下:這取決於,GHC有這樣一個擴展,但它並不總是足夠聰明,做你想做的。

+0

謝謝!順便說一句,對於無效的哈斯克爾抱歉。我拿了我從一個使用Haskell作爲例子的類論的論述中發佈的代碼,但作者並不總是清楚何時他是一個類似於Haskell的僞代碼而不是真正的Haskell。下次我會更清楚。 – kjo

+0

@kjo您的'type'代碼實際上是很好的Haskell,它只是無法爲這些實例添加實例。 –

+0

啊!我懂了。感謝您的澄清。 – kjo