[英]How are Arrows and Functions different in haskell?
我學習並搜索了一段時間的Arrows,我對Arrow課程的必要性感到有些困惑。 據我所知,Arrow類是函數的抽象,而Arrow A abc
表示需要輸入類型b和輸出類型c的東西。 此外,它提供了幾個基本操作,如>>>
, arr
和first
。
但是,我找不到類型b -> c
標准函數和類型A abc
箭頭之間的任何區別。 在我看來, first
, >>>
可以用\\(b, c) -> (fb, c)
和(.)
代替。 此外,由於箭頭內的每個計算都由函數表示,如果我們用這些函數替換箭頭,我認為沒有區別。
簡而言之,我認為Arrows的計算圖的每個節點(類似於https://www.haskell.org/arrows/syntax.html )都可以被Haskell的標准函數替代。 如果是真的,為什么我們使用Arrow而不是函數?
擁有符合某些法則的抽象允許您進行泛型編程。 你可以編程沒有任何類型類(沒有monad,applicatives,沒有相等/排序等),但這將是非常不方便的,因為你將無法編寫利用這些屬性的通用代碼。
就像你說你不想要Ord
實例一樣,然后你必須為你可以訂購的每種數據類型單獨重寫Set
的實現。
Arrow
的觀點是描述那些計算
所以箭頭A bc
不是函數a -> b
。 很可能箭頭在內部實現為一個函數,但是更復雜的一個,實現Arrow
接口的目的是描述(除其他外)它們如何構成。
特別是對於箭頭,您有箭頭符號 ,允許您對任何有效的Arrow
使用相同的表示法。 舉一個例子,在netwire包中, Wire
數據類型實現了Arrow
,因此您可以使用箭頭符號以及所有適用於箭頭的實用程序函數。 如果沒有實例,您必須具有一些特定於網絡的語法,或者只使用netwire提供的功能。
舉個例子:對應於State
monad的箭頭是a -> s -> (b, s)
。 但是兩個這樣的函數不使用(.)
。 你需要描述它們的構成,而這正是Arrow
所做的。
更新:可以有各種可組合性概念,但我想你的意思是功能組合。 是的,這個可組合性來自Arrow
的Category
超類,它定義了身份和組合。
Arrow
的另一部分來自Strong
profunctor,因為我最近從了什么是兼容者和箭頭之間的關系? (雖然這不是在類型層次結構中捕獲的,因為Profunctor
類型Profunctor
Arrow
更年輕)。 Profunctors允許由純計算從“雙方”改性,見lmap
/ rmap
/ dimap
在Profunctor
。 對於箭頭我們有(<<^)
和(^>>)
其被使用表達arr
和>>>
與純箭頭使用構成通過合成BV的箭頭從任一側arr
。
最后箭頭有強度 wrt (,)
,它由first :: Arrow a => abc -> a (b, d) (c, d)
捕獲。 這意味着我們只能在輸入的一部分上使用箭頭,而不會更改另一個。 這允許用“平行線”構造“電路” - first
不可能保存計算的一部分的輸出並且稍后在某處使用它。
一個很好的練習是繪制一個表示計算的電路,然后嘗試使用Arrow
原語/實用程序表達它,或者使用箭頭語法表示法。 你會看到first
(或***
)對此至關重要。
請參閱Arrows可以多任務獲取操作的精美圖紙。
對於更多理論背景箭頭是強Monads可能很有趣(我還沒有讀過)。
那是因為你只看到了Arrow
的(->)
實例。 其他類型也可以聲明Arrow
實例,其中操作更復雜。 例如:
instance Monad m => Arrow (Kleisli m) where
arr f = Kleisli (return . f)
first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.