2011-04-02 112 views

回答

9

當您函子的一個實例,你應該證明側面條件

fmap id = id 

fmap (f . g) = fmap f . fmap g 

(技術上後者免費的午餐考慮到所涉及的種類和前法,但它仍然是一個很好的鍛鍊。)

你不能這樣做只是說

fmap id = id 

而是你用這是一個推理工具 - 一旦你證明了它。

也就是說,你寫的代碼沒有意義,原因有很多。

(f . g) x = f (g x) 

由於這是縮進,我有點不清楚這是否意在成爲一個定義(。),但已經包含在前奏,所以你不必再定義它。

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

這個定義在Prelude中也提供給你。

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

但隨後再次定義類,但在這裏它已經錯位FMAP的簽名,這必須是

fmap :: (a -> b) -> g a -> g b 

但你有權上述函子的另一個定義(和序曲有另一個,你不能得到這編譯)

最後,您

instance Functor F where 
    fmap id = id 
    fmap (f . g) = fmap f . fmap g 

組成了一個名稱爲F的類型,您想將其作爲Functor的一個實例,然後嘗試將法律作爲實現來實現,而不是如何工作。

讓我們舉一個它應該如何工作的例子。

考慮一個非常簡單的函子:

data Pair a = Pair a a 

instance Functor Pair where 
    fmap f (Pair a b) = Pair (f a) (f b) 

現在,證明fmap id = id,讓我們考慮一下fmap idid做逐點:

fmap id (Pair a b) = -- by definition 
Pair (id a) (id b) = -- by beta reduction 
Pair a (id b) = -- by beta reduction 
Pair a b 

id (Pair a b) = -- by definition 
Pair a b 

所以,fmap id = id在這種特殊情況下。

然後你就可以檢查(雖然在技術上鑑於上述情況,你不必),其fmap f . fmap g = fmap (f . g)

(fmap f . fmap g) (Pair a b) = -- definition of (.) 
fmap f (fmap g (Pair a b)) = -- definition of fmap 
fmap f (Pair (g a) (g b)) = -- definition of fmap 
Pair (f (g a)) (f (g b)) 

fmap (f . g) (Pair a b) = -- definition of fmap 
Pair ((f . g) a) ((f . g) b) = -- definition of (.) 
Pair (f (g a)) ((f . g) b) = -- definition of (.) 
Pair (f (g a)) (f (g b)) 

所以fmap f . fmap g = fmap (f . g)

現在,你可以讓函數組合成一個仿函數。

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

部分應用函數的箭頭構造函數。

注意a -> b(->) a b意思是一樣的,所以當我們說

instance Functor ((->) e) where 

FMAP的簽名擅長於

fmap {- for (->) e -} :: (a -> b) -> (->) e a -> (->) e b 

它一旦你已經翻轉箭頭周圍的樣子

fmap {- for (->) e -} :: (a -> b) -> (e -> a) -> e -> b 

但這只是功能組合的簽名!

所以

instance Functor ((->)e) where 
    fmap f g x = f (g x) 

是一個完全合理的定義,甚至

instance Functor ((->)e) where 
    fmap = (.) 

,它實際上在Control.Monad.Instances顯示出來。

因此,所有你需要使用它是

import Control.Monad.Instances 

,你不需要編寫任何代碼來支持這一點,你可以使用fmap作爲函數組合作爲特殊情況,所以例如

fmap (+1) (*2) 3 = 
((+1) . (*2)) 3 = 
((+1) ((*2) 3)) = 
((+1) (3 * 2)) = 
3 * 2 + 1 = 
7 
2

由於.不是一個數據構造函數,你不能用它進行模式匹配,我相信。據我所知,儘管我對Haskell來說也很新穎,但並不是一種簡單的方法來做你想做的事情。

+0

你能舉一個正確的文字 – Jo0o0 2011-04-02 07:46:11

+0

@Super G:我不認爲你可以做到這一點。 – cobbal 2011-04-02 07:50:10

+0

如何添加一個函數組合來製作f。 g工作?如上所述是我想要做的一個例子。 – Jo0o0 2011-04-02 07:54:18

2

let不用於頂層的綁定,只是做:

f . g = \x -> f (g x) 

但投訴,如cobbal說,大約是fmap (f . g),這是無效的。其實,整個class Functor F where是擰緊。這個類已經聲明,現在我想你想和instance

instance Functor F where 
    fmap SomeConstructorForF = ... 
    fmap OtherConstructorForF = ... 

+0

沒有讓,將有:1:8:解析錯誤輸入'=' – Jo0o0 2011-04-02 08:36:31

+2

@超級G:你不能在GHCi中定義類或實例。你會得到你的語法錯誤。您需要在文件中定義它們,然後:在GHCi中加載該文件。當然,你會遇到各種其他的代碼錯誤,但這是你的根本問題。 – Carl 2011-04-02 08:54:06

+0

在文件中,我把它放在頂部。但是,模式中的分析錯誤:f。克,它似乎不使用線做功能組成 – Jo0o0 2011-04-02 09:07:52

相關問題