如何检测Monad? [英] How to detect a Monad?

查看:75
本文介绍了如何检测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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆