[英]Parse error in pattern: f . g in fmap (f . g) = fmap f . fmap g
模式中的解析錯誤:f。 G
我是初學者,哪里錯了?
(f . g) x = f (g x)
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor g where
fmap :: (a -> b) -> f a -> f b
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
當你創建一個Functor的實例時,你應該證明它的邊緣條件
fmap id = id
和
fmap (f . g) = fmap f . fmap g
(從技術上講,后者是免費的,因為涉及的類型和前法律,但它仍然是一個很好的練習。)
你不能這樣說
fmap id = id
但相反,你使用它作為推理工具 - 一旦你證明了它。
也就是說,由於多種原因,您編寫的代碼沒有意義。
(f . g) x = f (g x)
由於這是縮進的,我有點不清楚這是否是(。)的定義,但是已經包含在Prelude中,所以你不需要再次定義它。
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
但是正如你在上面有另一個Functor的定義(並且Prelude還有另一個,你無法編譯)
最后,你的
instance Functor F where
fmap id = id
fmap (f . g) = fmap f . fmap g
為你想要成為Functor
實例的類型組成一個名稱F
,然后嘗試將法律作為一個實現,這不是它的工作原理。
讓我們舉一個它應該如何工作的例子。
考慮一個非常簡單的仿函數:
data Pair a = Pair a a
instance Functor Pair where
fmap f (Pair a b) = Pair (f a) (f b)
現在,為了證明fmap id = id
,讓我們考慮一下fmap id
和id
做什么的:
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 = 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)
fmap f . fmap g = fmap (f . g)
現在,您可以將函數組合轉換為仿函數。
class Functor f where
fmap :: (a -> b) -> f a -> f b
通過部分應用函數箭頭構造函數。
注意a -> b
和(->) ab
意思相同,所以當我們說
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
自從.
不是數據構造函數,你不能用它來進行模式匹配我相信。 據我所知,沒有一種簡單的方法可以做你正在嘗試的事情,盡管我對Haskell也很新。
let
不用於頂級綁定,只需:
f . g = \x -> f (g x)
但是,正如cobbal所說,投訴是關於fmap (f . g)
,這是無效的。 實際上, class Functor F where
搞砸了。 該類已經聲明,現在我認為你想制作和instance
:
instance Functor F where
fmap SomeConstructorForF = ...
fmap OtherConstructorForF = ...
等等
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.