每種類型和類型的構造函數都有一種。簡單像Int
有種*
。你的單參數類型構造函數Users
有種類* -> *
;它需要一種類型並返回一個新類型。您的Users
的第一個示例具有種類* -> * -> * -> *
;需要三個類型並返回一個新的類型。
Functor
只適用於類型爲* -> *
的構造函數。這使您可以爲第二個Users
類型構造函數定義一個Functor
實例,但不是第一個。
想一想你的第一次嘗試:數據構造函數Users
需要三個參數,但是你的定義fmap
試圖用一個返回值f來調用它。你可以做Users
仿函數,只要你願意讓所有三個字段相同的類型:
data Users a = Users a a a
instance Functor Users where
fmap f (Users a b c) = Users (f a) (f b) (f c)
在理論上,你可以定義一個類Trifunctor
(有一個Bifunctor
類可用):
class Trifunctor f where
trimap :: (a1 -> b1) -> (a2 -> b2) -> (a3 -> b3) -> f a1 a2 a3 -> f b1 b2 b3
data Users a b c = Users a b c
instance Trifunctor Users where
trimap f g h (Users a b c) = Users (f a) (g b) (h c)
但它是有爭議的,這將是多麼有用。 Functor
對通用容器很有用,因爲它們具有廣泛的用途。另一方面,Users
看起來非常具體。您通常不需要您定義它的靈活性; data User = User Int Int Int
好像它可以正常工作,並且不需要將功能映射到此處:您需要多長時間一次以相同的方式修改身高,體重和年齡?
第二個例子並沒有做你認爲的事情 - 你需要對'fmap'進行縮進才能使它成爲實例的一部分。第一個示例省略了錯誤,它告訴你這個問題(n.b.這是一個類型問題,函子實例是'* - > *'類型的)。 –
'然而這不會編譯?'編譯器錯誤是什麼? –