如何检测Monad? [英] How to detect a Monad?
问题描述
我们中许多人没有功能编程的背景,更不用说类别理论代数。因此,让我们假设我们需要并因此创建一个泛型类型,如
data MySomething t = .......
然后我们继续编程,并使用 MySomething
。有什么证据可以提醒我们 MySomething
是一个单子,我们必须通过编写实例Monad MySomething ...
返回和>> =
为它?
感谢。
编辑:另请参阅以下问题:是链接操作monad类解决的唯一事情吗?,并且这个答案 monad是一个辅助操作函数的数组
A向我迈进了一大步,理解monad是一篇文章 Monads是嫁接树木。如果您的类型看起来像一棵树,并且叶子上出现 t
值,那么您可能手上有一个单子。
简单的例子
一些数据类型显然是树,例如 Maybe
type
data也许a = Nothing |只是一个
,它有一个空叶子或一个叶子具有单个值。该列表是另一种明显的树型
数据List a = Nil |缺点a(列表a)
这是一个空叶子或一个单一值的叶子,另一个列表。一棵更明显的树是二叉树
数据树a =叶a | Bin(Tree a)(Tree a)
包含树叶中的值。
较难的例子
然而,有些类型乍一看并不像树。例如,'reader'monad(又名函数monad或者环境monad)看起来就像
数据Reader ra = Reader {runReader: :r - > a}
目前看起来不像树。但让我们专注于具体类型 r
,例如 Bool
-
data ReaderBool a = ReaderBool(Bool - > a)
从 Bool
到 a
的函数相当于一对(a ,a)
其中该对的左边元素是 True
上函数的值,右边参数是<$ c $上的值c> False -
data ReaderBool a = ReaderBool aa
看起来更像一棵只有一种叶子的树 - 事实上,你可以把它变成一个monad
实例Monad ReaderBool其中
返回a = ReaderBool aa
ReaderBool ab>> = f = ReaderBool a'b '
其中
ReaderBool a'_ = fa
ReaderBool _b'= fb
道德是一个函数 r - >一个
可以被看作是一个很长的元组,它包含许多类型为 a
的值,每个可能的输入都有一个 - 并且该元组可以被看作是
状态monad是这种类型的另一个例子
data State sa = State {runState :: s - > (a,s)}
在这里您可以查看 s - > (a,s)
作为(a,s)
类型值的大元组 - 一个用于输入类型 s
。
再举一个例子 - 一个简化的IO操作monad
data Action a = Put String(Action a)
| Get(String - >操作a)
|返回一个
这是一棵有三种叶子的树 - Put > > > > > > c>字符串
输入)和一个简单的返回
叶子,它只携带一个类型 a
。所以它看起来可能是monad,实际上它是
instance Monad Action其中
return = Return
放置>> = f =放置s(a>> = f)
获取g>> = f = Get(\ s - > gs> ;> = f)
返回a>> = f = fa
这给了你一点直觉。
将单体想象为树,返回
操作作为一种方式用一个值得到一棵简单的树,用>> =
操作作为用新树代替树叶的元素的一种方式,可以是一种强大的统一看单子的方式。
Many of us don't have a background on functional programming, and much less on category theory algebra. So let's suppose that we need and therefore create a generic type like
data MySomething t = .......
Then we continue programming, and using MySomething
. What evidences should alert us that MySomething
is a monad, and that we have to make it one by writing instance Monad MySomething ...
and defining return
and >>=
for it?
Thanks.
Edit: See also this question: is chaining operations the only thing that the monad class solves?, and this answer a monad is an array of functions with helper operations
A big step forward for me in my understanding of monads was the post Monads are Trees with Grafting. If your type looks like a tree, and the t
values appear at the leaves, then you may have a monad on your hands.
Simple examples
Some data types are obviously trees, for example the Maybe
type
data Maybe a = Nothing | Just a
which either has a null leaf, or a leaf with a single value. The list is another obvious tree type
data List a = Nil | Cons a (List a)
which is either a null leaf, or a leaf with a single value and another list. An even more obvious tree is the binary tree
data Tree a = Leaf a | Bin (Tree a) (Tree a)
with values at the leaves.
Harder examples
However, some types don't look like trees at first glance. For example, the 'reader' monad (aka function monad or environment monad) looks like
data Reader r a = Reader { runReader :: r -> a }
Doesn't look like a tree at the moment. But let's specialize to a concrete type r
, for example Bool
--
data ReaderBool a = ReaderBool (Bool -> a)
A function from Bool
to a
is equivalent to a pair (a,a)
where the left element of the pair is the value of the function on True
and the right argument is the value on False
--
data ReaderBool a = ReaderBool a a
which looks a lot more like a tree with only one type of leaf - and indeed, you can make it into a monad
instance Monad ReaderBool where
return a = ReaderBool a a
ReaderBool a b >>= f = ReaderBool a' b'
where
ReaderBool a' _ = f a
ReaderBool _ b' = f b
The moral is that a function r -> a
can be viewed as a big long tuple containing many values of type a
, one for each possible input - and that tuple can be viewed as the leaf of a particularly simple tree.
The state monad is another example of this type
data State s a = State { runState :: s -> (a, s) }
where you can view s -> (a, s)
as a big tuple of values of type (a, s)
-- one for possible input of type s
.
One more example - a simplified IO action monad
data Action a = Put String (Action a)
| Get (String -> Action a)
| Return a
This is a tree with three types of leaf -- the Put
leaf which just carries another action, the Get
leaf, which can be viewed as an infinite tuple of actions (one for each possible String
input) and a simple Return
leaf that just carries a single value of type a
. So it looks like it might be a monad, and indeed it is
instance Monad Action where
return = Return
Put s a >>= f = Put s (a >>= f)
Get g >>= f = Get (\s -> g s >>= f)
Return a >>= f = f a
Hopefully that's given you a little bit of intuition.
Thinking of monads as trees, the return
operation as a way of getting a simple tree with one value, and the >>=
operation as a way replacing the elements at the leaves of the tree with new trees, can be a powerful unifying way to look at monads.
这篇关于如何检测Monad?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!