Haskell`palindrome=reverse>>;=(==)`

Haskell`palindrome=reverse>>;=(==)`,haskell,functional-programming,monads,Haskell,Functional Programming,Monads,有人能解释一下Haskell中回文函数的工作原理吗: 回文::Eq a=>[a]->Bool 回文=反向>>=(==) --类型声明 反向::[a]->[a] >>=::单子m=>MA->(a->MB)->MB (反向>>=)::([a]->[a]->b)->[a]->b (==)::等式a=>a->a->Bool 特别是,Monad typeclass在函数上的定义是如何工作的,以及它是如何以某种方式将(=)的输入数量从两个列表减少到一个列表的?我认为这将是一个扩展,我在其中解释了函数是如何

有人能解释一下Haskell中回文函数的工作原理吗:

回文::Eq a=>[a]->Bool
回文=反向>>=(==)
--类型声明
反向::[a]->[a]
>>=::单子m=>MA->(a->MB)->MB
(反向>>=)::([a]->[a]->b)->[a]->b
(==)::等式a=>a->a->Bool

特别是,Monad typeclass在函数上的定义是如何工作的,以及它是如何以某种方式将(=)的输入数量从两个列表减少到一个列表的?

我认为这将是一个扩展,我在其中解释了函数是如何作为函子和应用程序的。让我从同一句话开始

我们可以考虑函数(<代码>(->)R < /代码>)作为一个包含已应用的值的上下文。这里我们有一个

reverse
函数,它包含一个反向列表,但只有将它应用到列表中才能得到它。让我们记住bind的类型签名

>>= :: Monad m => m a -> (a -> m b) -> m b
此处
ma
reverse
功能,
m
内的
a
是反向列表
(==)
(a->mb)
mb
a->Bool
。因此,
>=
返回一个
mb
,这只是一个函数,它接受一个列表并返回一个
Bool
。这是一致的,因为我们在函数monad中,所以它接受一个monad(函数)并返回另一个。只有当我们使用列表调用返回的一个时,整个机制才会运行。
ma
mb
都应用于提供的列表

手动实现
(>)r
的monad实例如下

return x = \_ -> x -- aka const
f >>= g = \r -> g (f r) r
如果我们仔细研究这一点,我们会注意到
>=
实际上是
(>)r
类型的
的翻转版本。但是当我说fllipped时要小心,它并不是指g=
f>=g

g <*> f = \x -> g x (f x)
f >>= g = \x -> g (f x) x
gf=\x->gx(fx)
f>>=g=\x->g(f x)x

这有点令人兴奋,所以请系上安全带:-)

monad是一个类型构造函数,它接受一个类型参数。例如,
可能是这样一个类型构造函数。所以,
可能
是一个单子,然后
可能Int
是该单子中的一个单子值。类似地,
IO
是单子,然后
IO Int
是该单子中的一元值

现在,还可以从具有两个类型参数的类型构造函数中生成monad。要做到这一点,我们只需要修复第一个。例如,查看
:它有两个参数,但monad必须只有一个参数。所以我们修正了第一个参数。因此,
或者Bool
是一个单子,然后
或者Bool Int
是该单子中的一个单子值。类似地,
任一字符串
是一个完全不同的单子,然后
任一字符串Int
是该单子中的一元值

另一方面,看看函数是如何表示的:

a -> b
但这只是中缀操作符的诡计,类似于
5+42
“foo”“bar”
。这种中缀符号可以像这样“规范化”:

(->) a b
所以实际上,“function”可以看作是一个类型构造函数,它有两个类型参数,就像
或者
一样。对于“函数”构造函数,这些参数具有特定的含义-一个是“函数输入”,另一个是“函数输出”

好了,现在我们准备把函数看作单子。就像使用
一样,为了做到这一点,我们必须修复第一个类型参数。因此,例如,
(>)Bool
是单子,然后
(>)Bool Int
(也称为
Bool->Int
)是该单子中的一元值。类似地,
(>)String
是一个完全不同的单子,而
(>)String Int
(也称为
String->Int
)是该单子中的一个单子值

给你一个直觉,一种看待它的方式是,这种单子中的一元值意味着“承诺”——也就是说,“你给我一个
字符串,我给你一个
Int
”。然后,标准的一元合成可以让你一起合成这样的承诺,就像你合成
IO
动作一样

到目前为止和我在一起?好的,很好

现在让我们看看如何实现绑定(aka
>=
)。
>>=
的签名如下:

(>>=) :: m a -> (a -> m b) -> m b
现在让我们专门讨论函数。现在,让我们假设,
m-Bool
。然后我们有:

(>>=) :: (->) Bool a -> (a -> (->) Bool b) -> (->) Bool b
或者,如果我们以中缀形式重写
(>)
构造函数,我们会得到:

(>>=) :: (Bool -> a) -> (a -> (Bool -> b)) -> (Bool -> b)
因此,您可以看到-绑定接受“承诺
a
”,然后将函数从
a
转换为“承诺
b
”,然后返回“承诺
b
”。因此,实现是微不足道的:

(>>=) :: (Bool -> a) -> (a -> (Bool -> b)) -> (Bool -> b)
(>>=) promiseOfA f = \theBool -> f (promiseOfA theBool) theBool

函数的monad实例称为“Reader monad”。如果你查一下,你应该可以在网上找到很多关于这是如何工作的文章。