什麼是免費monad?

本文翻譯自:What are free monads?

I've seen the term Free Monad pop up every now and then for some time, but everyone just seems to use/discuss them without giving an explanation of what they are. 我見過的長期無單子彈出每一個 現在 隨後一段時間,但每個人似乎只是使用/討論這些問題沒有給予它們是什麼解釋。 So: what are free monads? 所以:什麼是免費的monads? (I'd say I'm familiar with monads and the Haskell basics, but have only a very rough knowledge of category theory.) (我會說我熟悉monad和Haskell的基礎知識,但對類別理論只有非常粗略的瞭解。)


#1樓

參考:https://stackoom.com/question/u1W9/什麼是免費monad


#2樓

A free foo happens to be the simplest thing that satisfies all of the 'foo' laws. 一個免費的foo恰好是滿足所有'foo'定律的最簡單的東西。 That is to say it satisfies exactly the laws necessary to be a foo and nothing extra. 也就是說它完全滿足成爲foo所必需的法則,而不是額外的。

A forgetful functor is one that "forgets" part of the structure as it goes from one category to another. 一個健忘的仿函數是一個“忘記”結構的一部分,因爲它從一個類別到另一個類別。

Given functors F : D -> C , and G : C -> D , we say F -| G 假設F : D -> CG : C -> D ,我們說F -| G F -| G , F is left adjoint to G , or G is right adjoint to F whenever forall a, b: F a -> b is isomorphic to a -> G b , where the arrows come from the appropriate categories. F -| GFG伴隨,或者GF伴隨F ,b: F a -> ba -> G b同構,其中箭頭來自適當的類別。

Formally, a free functor is left adjoint to a forgetful functor. 正式地,一個自由的仿函數與一個健忘的仿函數相伴。

The Free Monoid 自由幺半羣

Let us start with a simpler example, the free monoid. 讓我們從一個更簡單的例子開始,即免費的幺半羣。

Take a monoid, which is defined by some carrier set T , a binary function to mash a pair of elements together f :: T → T → T , and a unit :: T , such that you have an associative law, and an identity law: f(unit,x) = x = f(x,unit) . 取一個monoid,由一些載體集T定義,一個二元函數將一對元素混合在一起f :: T → T → T ,和一個unit :: T ,這樣你就有了一個關聯定律和一個單一的定律: f(unit,x) = x = f(x,unit)

You can make a functor U from the category of monoids (where arrows are monoid homomorphisms, that is, they ensure they map unit to unit on the other monoid, and that you can compose before or after mapping to the other monoid without changing meaning) to the category of sets (where arrows are just function arrows) that 'forgets' about the operation and unit , and just gives you the carrier set. 你可以從monoids類別中創建一個函子U (其中箭頭是monoid同態,也就是說,它們確保它們將unit映射到另一個monoid上的unit ,並且你可以在映射到另一個monoid之前或之後組合而不改變含義)對於操作和unit “忘記”的集合類別(箭頭只是功能箭頭),只給你載體集。

Then, you can define a functor F from the category of sets back to the category of monoids that is left adjoint to this functor. 然後,您可以將一個仿函數F從集合的類別定義回與該仿函數相伴的monoids類別。 That functor is the functor that maps a set a to the monoid [a] , where unit = [] , and mappend = (++) . 該仿函數是將集合a映射到monoid [a]的函子,其中unit = []mappend = (++)

So to review our example so far, in pseudo-Haskell: 那麼到目前爲止,回顧我們的例子,在僞Haskell中:

U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a

F : Set → Mon -- is our free functor
F a = ([a],(++),[])

Then to show F is free, need to demonstrate that it is left adjoint to U , a forgetful functor, that is, as we mentioned above, we need to show that 然後爲了表明F是免費的,需要證明它與U ,一個健忘的仿函數相伴,也就是說,正如我們上面提到的,我們需要證明

F a → b is isomorphic to a → U b F a → ba → U b同構

now, remember the target of F is in the category Mon of monoids, where arrows are monoid homomorphisms, so we need a to show that a monoid homomorphism from [a] → b can be described precisely by a function from a → b . 現在,記住F的目標是幺半羣的類別Mon ,其中箭頭是幺半羣同態,所以我們需要一個來證明來自[a] → b的幺半羣同態可以用a → b的函數精確描述。

In Haskell, we call the side of this that lives in Set (er, Hask , the category of Haskell types that we pretend is Set), just foldMap , which when specialized from Data.Foldable to Lists has type Monoid m => (a → m) → [a] → m . 在Haskell中,我們稱之爲Set (er, Hask ,我們假裝設置的Haskell類型的類別),只是foldMap ,當從Data.Foldable到Lists專用時,類型爲Monoid m => (a → m) → [a] → m

There are consequences that follow from this being an adjunction. 這是一個附帶的後果。 Notably that if you forget then build up with free, then forget again, its just like you forgot once, and we can use this to build up the monadic join. 值得注意的是,如果你忘記然後自由積累,那麼再次忘記,它就像你忘了一次,我們可以用它來建立monadic連接。 since UFUF ~ U(FUF) ~ UF , and we can pass in the identity monoid homomorphism from [a] to [a] through the isomorphism that defines our adjunction,get that a list isomorphism from [a] → [a] is a function of type a -> [a] , and this is just return for lists. 因爲UFUF ~ U(FUF) ~ UF ,我們可以通過定義我們的adjunction的同構,從[a][a]傳遞同一性的monoid同態,從[a] → [a]獲得一個列表同構類型a -> [a]函數,這只是列表的返回。

You can compose all of this more directly by describing a list in these terms with: 您可以通過使用以下術語描述列表來直接撰寫所有這些內容:

newtype List a = List (forall b. Monoid b => (a -> b) -> b)

The Free Monad 免費Monad

So what is a Free Monad ? 什麼是免費Monad

Well, we do the same thing we did before, we start with a forgetful functor U from the category of monads where arrows are monad homomorphisms to a category of endofunctors where the arrows are natural transformations, and we look for a functor that is left adjoint to that. 好吧,我們做了我們之前做過的同樣的事情,我們從一個健忘的仿函數U開始,從monad類別中箭頭是monad homomorphisms到一類endofunctors,其中箭頭是自然變換,我們尋找一個左邊伴隨的仿函數那個。

So, how does this relate to the notion of a free monad as it is usually used? 那麼,這與通常使用的免費monad的概念有什麼關係呢?

Knowing that something is a free monad, Free f , tells you that giving a monad homomorphism from Free f -> m , is the same thing (isomorphic to) as giving a natural transformation (a functor homomorphism) from f -> m . 知道了什麼是一個免費的單子, Free f ,告訴你,從給定的單子同態Free f -> m ,是同樣的事情(同構)爲給從自然轉化(仿函數同態) f -> m Remember F a -> b must be isomorphic to a -> U b for F to be left adjoint to U. U here mapped monads to functors. 記住F a -> b必須與a -> U b同構,以便F與U同伴。這裏將monad映射到仿函數。

F is at least isomorphic to the Free type I use in my free package on hackage. F至少與我在hackage上的free軟件包中使用的Free類型同構。

We could also construct it in tighter analogy to the code above for the free list, by defining 我們還可以通過定義來構建它,以類似於上面的代碼爲自由列表

class Algebra f x where
  phi :: f x -> x

newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)

Cofree Comonads Cofree Comonads

We can construct something similar, by looking at the right adjoint to a forgetful functor assuming it exists. 我們可以構造類似的東西,通過查看正確的伴隨假定它存在的健忘函子。 A cofree functor is simply /right adjoint/ to a forgetful functor, and by symmetry, knowing something is a cofree comonad is the same as knowing that giving a comonad homomorphism from w -> Cofree f is the same thing as giving a natural transformation from w -> f . 一個cofree仿函數簡單/正確伴隨/一個健忘的仿函數,並且通過對稱性,知道一些cofree comonad就像知道從w -> Cofree f給出一個comonad homomorphism一樣,就像給出一個自然變換一樣w -> f


#3樓

Edward Kmett's answer is obviously great. Edward Kmett的回答顯然很棒。 But, it is a bit technical. 但是,它有點技術性。 Here is a perhaps more accessible explanation. 這是一個可能更容易理解的解釋。

Free monads are just a general way of turning functors into monads. 免費monad只是將仿函數轉換爲monad的一般方法。 That is, given any functor f Free f is a monad. 也就是說,給定任何仿函數f Free f是monad。 This would not be very useful, except you get a pair of functions 除非你得到一對函數,否則這不會很有用

liftFree :: Functor f => f a -> Free f a
foldFree :: Functor f => (f r -> r) -> Free f r -> r

the first of these lets you "get into" your monad, and the second one gives you a way to "get out" of it. 第一個讓你“進入”你的monad,第二個給你一個“走出去”它的方法。

More generally, if X is a Y with some extra stuff P, then a "free X" is aa way of getting from a Y to an X without gaining anything extra. 更一般地說,如果X是帶有一些額外東西P的Y,那麼“自由X”是從Y到X而不獲得額外任何東西的一種方式。

Examples: a monoid (X) is a set (Y) with extra structure (P) that basically says it has an operation (you can think of addition) and some identity (like zero). 示例:monoid(X)是具有額外結構(P)的集合(Y),基本上表示它具有操作(您可以想到添加)和一些身份(如零)。

So 所以

class Monoid m where
   mempty  :: m
   mappend :: m -> m -> m

Now, we all know lists 現在,我們都知道列表

data [a] = [] | a : [a]

Well, given any type t we know that [t] is a monoid 好吧,給任何類型的t我們知道, [t]是幺

instance Monoid [t] where
  mempty   = []
  mappend = (++)

and so lists are the "free monoid" over sets (or in Haskell types). 所以列表是集合(或Haskell類型)中的“免費幺半羣”。

Okay, so free monads are the same idea. 好吧,所以免費的monad是一樣的想法。 We take a functor, and give back a monad. 我們帶一個仿函數,然後給一個monad。 In fact, since monads can be seen as monoids in the category of endofunctors, the definition of a list 事實上,由於monads可以被視爲endofunctors類別中的monoids,因此定義了一個列表

data [a] = [] | a : [a]

looks a lot like the definition of free monads 看起來很像免費monads的定義

data Free f a = Pure a | Roll (f (Free f a))

and the Monad instance has a similarity to the Monoid instance for lists 並且Monad實例與列表的Monoid實例具有相似性

--it needs to be a functor
instance Functor f => Functor (Free f) where
  fmap f (Pure a) = Pure (f a)
  fmap f (Roll x) = Roll (fmap (fmap f) x)

--this is the same thing as (++) basically
concatFree :: Functor f => Free f (Free f a) -> Free f a
concatFree (Pure x) = x
concatFree (Roll y) = Roll (fmap concatFree y)

instance Functor f => Monad (Free f) where
  return = Pure -- just like []
  x >>= f = concatFree (fmap f x)  --this is the standard concatMap definition of bind

now, we get our two operations 現在,我們得到了兩個操作

-- this is essentially the same as \x -> [x]
liftFree :: Functor f => f a -> Free f a
liftFree x = Roll (fmap Pure x)

-- this is essentially the same as folding a list
foldFree :: Functor f => (f r -> r) -> Free f r -> r
foldFree _ (Pure a) = a
foldFree f (Roll x) = f (fmap (foldFree f) x)

#4樓

A Haskell free monad is a list of functors. Haskell免費monad是一個仿函數列表。 Compare: 相比:

data List a   = Nil    | Cons  a (List a  )

data Free f r = Pure r | Free (f (Free f r))

Pure is analogous to Nil and Free is analogous to Cons . Pure類似於NilFree類似於Cons A free monad stores a list of functors instead of a list of values. 免費monad存儲一個函子列表而不是值列表。 Technically, you could implement free monads using a different data type, but any implementation should be isomorphic to the above one. 從技術上講,您可以使用不同的數據類型實現免費monad,但任何實現都應該與上面的實現同構。

You use free monads whenever you need an abstract syntax tree. 只要需要抽象語法樹,就可以使用免費的monad。 The base functor of the free monad is the shape of each step of the syntax tree. free monad的基礎仿函數是語法樹每一步的形狀。

My post , which somebody already linked, gives several examples of how to build abstract syntax trees with free monads 我的帖子 ,有人已經鏈接,提供了幾個如何使用免費monad構建抽象語法樹的示例


#5樓

Here's an even simpler answer: A Monad is something that "computes" when monadic context is collapsed by join :: m (ma) -> ma (recalling that >>= can be defined as x >>= y = join (fmap yx) ). 這裏有一個更簡單的答案:當monadic上下文被join :: m (ma) -> ma摺疊時,Monad就是“計算”的東西(回想一下>>=可以定義爲x >>= y = join (fmap yx) )。 This is how Monads carry context through a sequential chain of computations: because at each point in the series, the context from the previous call is collapsed with the next. 這就是Monads如何通過順序計算鏈傳遞上下文:因爲在序列中的每個點,前一個調用的上下文與下一個調用一起摺疊。

A free monad satisfies all the Monad laws, but does not do any collapsing (ie, computation). 一個免費的monad滿足所有Monad定律,但不做任何崩潰(即計算)。 It just builds up a nested series of contexts. 它只是構建了一系列嵌套的上下文。 The user who creates such a free monadic value is responsible for doing something with those nested contexts, so that the meaning of such a composition can be deferred until after the monadic value has been created. 創建這樣一個自由monadic值的用戶負責使用那些嵌套的上下文做某事,這樣這個組合的含義可以推遲到創建monadic值之後。


#6樓

I think a simple concrete example will help. 我認爲一個簡單的具體例子會有所幫助。 Suppose we have a functor 假設我們有一個仿函數

data F a = One a | Two a a | Two' a a | Three Int a a a

with the obvious fmap . 用明顯的fmap Then Free F a is the type of trees whose leaves have type a and whose nodes are tagged with One , Two , Two' and Three . 然後Free F a是葉子類型爲a且其節點標記爲OneTwoTwo'Three的樹的類型。 One -nodes have one child, Two - and Two' -nodes have two children and Three -nodes have three and are also tagged with an Int . One節點有一個子節點, Two節點和Two'節點有兩個子節點, Three節點有三個節點,並且還用Int標記。

Free F is a monad. Free F是monad。 return maps x to the tree that is just a leaf with value x . return map x映射到只是值爲x的葉子的樹。 t >>= f looks at each of the leaves and replaces them with trees. t >>= f查看每個葉子並用樹替換它們。 When the leaf has value y it replaces that leaf with the tree fy . 當葉子具有值y它用樹fy替換該葉子。

A diagram makes this clearer, but I don't have the facilities for easily drawing one! 圖表使這更清楚,但我沒有輕鬆繪製一個的設施!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章