簡體   English   中英

模式中的解析錯誤:f。 g在fmap中(f.g)= fmap f。 fmap g

[英]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 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 = 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM