Function 单子与函数的区别
好的,关于Monad,我知道已经问了足够多的问题。我不想再打扰任何人去问什么是单子 事实上,我读过,这是非常有帮助的。我觉得我离真正理解它很近了 我在这里提出这个问题只是为了描述我对单子和函数的一些想法,希望有人能纠正我或确认它是正确的Function 单子与函数的区别,function,functional-programming,monads,Function,Functional Programming,Monads,好的,关于Monad,我知道已经问了足够多的问题。我不想再打扰任何人去问什么是单子 事实上,我读过,这是非常有帮助的。我觉得我离真正理解它很近了 我在这里提出这个问题只是为了描述我对单子和函数的一些想法,希望有人能纠正我或确认它是正确的 那篇文章中的一些答案让我觉得monad有点像函数 Monad接受一个类型,返回一个包装类型(return),也可以接受一个类型,对它执行一些操作,并返回一个包装类型(bind) 在我看来,它有点像函数。函数获取某些内容并执行某些操作,然后返回某些内容 那我们为
那篇文章中的一些答案让我觉得monad有点像函数 Monad接受一个类型,返回一个包装类型(
return
),也可以接受一个类型,对它执行一些操作,并返回一个包装类型(bind
)
在我看来,它有点像函数。函数获取某些内容并执行某些操作,然后返回某些内容
那我们为什么还要monad?我认为其中一个关键原因是monad为初始数据/类型的顺序操作提供了更好的方式或模式
例如,我们有一个初始整数i
。在我们的代码中,我们需要一步一步地应用10个函数f1,f2,f3,f4,…,f10
,也就是说,我们首先对i
应用f1
,得到一个结果,然后对该结果应用f2
,然后我们得到一个新的结果,然后应用f3
我们可以通过函数rawly实现这一点,就像f1 i |>f2 |>f3…
。然而,这些步骤的中间结果并不一致;此外,如果我们不得不在中间的某个地方处理可能的失败,事情就会变得糟糕。如果我们不希望整个过程在异常时失败,那么无论如何都必须构造一个选项。所以很自然地,monad
出现了
Monad统一并强制所有步骤中的返回类型。这大大简化了代码的逻辑和可读性(这也是那些设计模式的目的,不是吗)。此外,它对错误或bug更具防弹性。例如,Option Monad
强制每个中间结果都是options
,并且很容易实现快速失败
范例
正如许多关于monad的文章所描述的那样,monad是一种设计模式,是组合函数/步骤以构建流程的更好方式
我理解正确吗?我觉得你似乎在发现类比学习的局限性。Monad在Haskell中被精确地定义为一个类型类,在范畴论中被定义为一个代数对象;任何使用“…像…”的比较都是不精确的,因此是错误的
所以不,因为Haskell的单子与函数不同,因为它们1)是作为类型类实现的,2)旨在以不同于函数的方式使用
这个答案可能并不令人满意;你在寻找直觉吗?如果是这样的话,我建议做大量的例子,尤其是通读。如果没有坚实的实例和经验基础,很难直观地理解像单子这样的抽象事物
为什么我们甚至需要单子?这是一个好问题,也许这里有不止一个问题:
为什么我们甚至需要Monad类型类?原因与我们需要任何类型类相同
为什么我们甚至需要monad概念?因为它很有用。而且,它不是一个函数,所以它不能被函数替换。(您的示例似乎不需要Monad(相反,它需要一个应用程序)
例如,您可以使用Applicative type类实现上下文无关的解析器组合器。但是,请尝试在不使用Monad的情况下为包含相同符号字符串的语言实现两次解析器(用空格分隔),即:
a a -> yes
a b -> no
ab ab -> yes
ab ba -> no
所以这是单子提供的一件事:使用先前的结果来“决定”做什么的能力。下面是另一个例子:
f :: Monad m => m Int -> m [Char]
f m =
m >>= \x ->
if x > 2
then return (replicate x 'a')
else return []
f (Just 1) -->> Just ""
f (Just 3) -->> Just "aaa"
f [1,2,3,4] -->> ["", "", "aaa", "aaaa"]
单子(和函子,和应用函子)可以看作是关于“广义函数应用”:它们都创建fa类型的函数⟶ f b
不仅涉及“上下文中的值”,如类型a
和b
,而且还涉及“上下文”——相同类型的上下文——由f
表示
因此,“正常”函数应用涉及(a)类型的函数⟶ b)
,“通用”函数应用程序的函数类型为(f a⟶ f b)
。由于更统一的类型结构:fa,这样的函数也可以在正常的函数组合下组合⟶ f b;f-b⟶ f c==>f a⟶ f c
三个中的每一个都以不同的方式创建它们,从不同的事情开始:
Functors: fmap :: Functor f => (a ⟶ b) ⟶ (f a ⟶ f b)
Applicative Functors: (<*>) :: Applicative f => f (a ⟶ b) ⟶ (f a ⟶ f b)
Monadic Functors: (=<<) :: Monad f => (a ⟶ f b) ⟶ (f a ⟶ f b)
以及他们的类型,
"liftF1" :: (Functor f) => (a ⟶ b) ⟶ f a ⟶ f b -- fmap
liftA2 :: (Applicative f) => (a ⟶ b ⟶ c) ⟶ f a ⟶ f b ⟶ f c
"liftBind" :: (Monad f) => (a ⟶ b ⟶ c) ⟶ f a ⟶ (a ⟶ f b) ⟶ f c
"liftF1" :: (Functor f) => (a ⟶ b) ⟶ f a ⟶ f b -- fmap
liftA2 :: (Applicative f) => (a ⟶ b ⟶ c) ⟶ f a ⟶ f b ⟶ f c
"liftBind" :: (Monad f) => (a ⟶ b ⟶ c) ⟶ f a ⟶ (a ⟶ f b) ⟶ f c