[英]Deriving monad bind from applicative (<*>) confusion
通過Haskell Book和我的大腦正在打破下面的例子。 我真的不知道第21行的flip
功能是做什么的
1 class Functor f where
2 fmap :: (a -> b) -> f a -> f b
3
4 class Functor f => Applicative f where
5 pure :: a -> f a
6 (<*>) :: f (a -> b) -> f a -> f b
7
8 class Applicative f => Monad f where
9 return :: a -> f a
10 (>>=) :: f a -> (a -> f b) -> f b
11
12 instance Functor ((->) r) where
13 fmap = (.)
14
15 instance Applicative ((->) r) where
16 pure = const
17 f <*> a = \r -> f r (a r)
18
19 instance Monad ((->) r ) where
20 return = pure
21 ra >>= arb = flip arb <*> ra
-- flip :: (a -> b -> c) -> b -> a -> c
-- ra >>= arb = flip arb <*> ra
據我了解,flip接受一個函數,它接受兩個參數,然后是兩個單獨的參數,並返回一個值。 在綁定示例中,我們將arb
作為(a -> b -> c)
傳遞,然后將<*>
作為b
的翻轉簽名,最后ra
作為a
? 我看不出來。
我已經嘗試使類型更具體到我的實際示例,所以你可以重寫<*>
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
我也可以為綁定做同樣的事情
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
所以即使像我這樣的假人也可以看到,如果我們可以交換<*>
,我們就可以排隊了
(<???>) :: (r -> a) -> (r -> a -> b) -> (r -> b)
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
但是看那里的第二個參數,第一個想要一個r
作為它的第一個參數,而bind想要一個a
所以不知何故flip
是本書的例子是為我們做的,但我真的不明白如何。 任何幫助將不勝感激。
謝謝!
我認為頂級的混淆點是: flip
正在修改arb
,而不是修改<*>
因為你似乎相信。 我們已經“修改”了<*>
以獲得“正確”的參數順序,只是通過以與我們得到它們相反的順序給出<*>
它的參數!
現在詳細說明。 正如你所說,我們有:
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
所以,既然我們在左手邊寫了
ra >>= arb = ...
那么我們的范圍是:
ra :: r -> a
arb :: a -> r -> b
(注意如何選擇名稱來反映類型!)重寫你給flip
的類型,我們有
flip :: (a -> b -> c) -> b -> a -> c -- original
flip :: (a -> r -> b) -> r -> a -> b -- rename variables
因此:
flip arb :: r -> a -> b
現在回想一下你寫的(<*>)
的類型:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
因此,對於(<*>)
的第一個參數,我們需要類型為r -> a -> b
。 嘿! flip arb
有那種類型! 對於第二個參數,我們需要r -> a
類型的東西。 我們再次幸運,因為ra
有這種類型,所以......
flip arb <*> ra :: r -> b
(和中綴運算符一樣,這是運算符(<*>)
的應用,參數flip arb
和ra
。)我們希望有什么類型的? 好吧,我們現在回到(>>=)
的類型:
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
在取兩個參數之后,這應該返回r -> b
類型的東西。 很酷,這就是我們建立的。
ra >>= arb = flip arb <*> ra
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.