2017-04-03 43 views
3

我有以下類型newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a }。 而且我得到了寫函子實例吧,但我真的不明白,我怎麼 試圖Functor的實例

instance Functor (Arr2 e1 e2) where 
    fmap g (Arr2 a) = Arr2 (g a) 

instance Functor (Arr2 e1 e2) where 
    fmap g = g . getArr2 

這實際上導致類型

(a -> b) -> Arr2 e1 e2 a -> b 

代替所需的

(a -> b) -> Arr2 e1 e2 a -> Arr2 e1 e2 b 

所以,請幫我

回答

4

Functor類有作爲的定義:

class Functor f where: 
    fmap :: (a -> b) -> f a -> f b 
    (<$) :: a -> f b -> f a 

(<$)有一個默認的實現:(<$) = fmap . const工作正常。

因此,這意味着,如果我們進入一個函數(g :: a -> b)作爲第一個參數,併產生一個aArr2,我們不得不產生一個Arr2調用該g上的箭頭的結果如果它被應用。

結果的fmapArr2的定義是:

instance Functor (Arr2 e1 e2) where 
    fmap g (Arr2 a) = Arr2 (\x y -> g (a x y))

或者更優雅:

instance Functor (Arr2 e1 e2) where 
    fmap g (Arr2 a) = Arr2 (\x -> g . (a x))

或者更優雅的版本 - 由@Alec評論:

instance Functor (Arr2 e1 e2) where 
    fmap g (Arr2 a) = Arr2 ((g .) . a)

(您可以將表達式轉換爲對pointfree那些使用this tool

+2

如果你想得到更多的不可讀優雅,你可以做'fmap g(Arr2 a)= Arr2((g。))。一)'。 – Alec

+0

@Alec:是的。謝謝你的建議。更新。 –

+2

當pointfree超出一個參數時,我喜歡使用[SECs](http://conal.net/blog/posts/semantic-editor-combinators)。這個'(。)'部分的廢話從來沒有吸引過我 – luqui

0

Willem Van Onsem提供的答案是很不錯的,我只是想建議使用一種語言擴展,可以輕鬆地創建Functor實例爲newtypes的:DeriveFunctor

在您的模塊的頂部,你可以添加:

{-# LANGUAGE DeriveFunctor #-} 

然後你就可以自動地得到您的Functor例如:

newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a } deriving Functor 

這裏的是我會怎樣找出類型在GHCi中的這個實例的fmap

λ > :set -XDeriveFunctor 
λ > newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a } deriving Functor 
λ > :set -XTypeApplications 
λ > :t fmap @(Arr2 _ _) 
fmap @(Arr2 _ _) :: (a -> b) -> Arr2 t t1 a -> Arr2 t t1 b 
相關問題