在这个函数中与 =<< 一起使用的 monad 是什么?

Cal*_*pau 4 monads haskell

一个1-Haskell-a-Day 练习让我困惑到无法回头。目标是过滤掉列表中的元素,除非它等于以下元素。例如

> filterByPair [1, 2, 2, 2, 3, 3, 4]
[2,2,3]
Run Code Online (Sandbox Code Playgroud)

(我试图制作两个偏移量列表,将它们压缩成元组并删除两次没有相同数字的元组,例如 [(2,2),(2,2),(3,3)],等)但令人兴奋的简单解决方案使用=<<绑定运算符:

filterByPair :: Eq a => [a] -> [a]
filterByPair = (init =<<) . group
Run Code Online (Sandbox Code Playgroud)

我很难弄清楚那个运算符。当我尝试使用 ghci 时,我没有得到相同的结果:

> init =<< [2,3,4]
No instance for (Num [b0]) arising from the literal `2'
Run Code Online (Sandbox Code Playgroud)

我发现在 ghci 中我可以使用,比如说,replicate=<<. 它似乎将列表的每个元素都输入到函数中:

> replicate 2 =<< [2,3,4]
[2,2,3,3,4,4]
Run Code Online (Sandbox Code Playgroud)

所以第一次复飞相当于:

> replicate 2 2
[2,2]
Run Code Online (Sandbox Code Playgroud)

它以某种方式知道将列表放在 的第二个参数中replicate,而不是第一个参数中,并将它们全部输出到一个大列表中而不是单独的列表中,就像fmap这样:

> fmap (replicate 2) [2,3,4]
[[2,2],[3,3],[4,4]]
Run Code Online (Sandbox Code Playgroud)

我读过绑定运算符是由正在使用的 monad 定义的。这是一个 monad 函数,不是吗?monad 在哪里filterByPair?它与Eq签名中的类型类有关吗?

同样,如果我=<<在 ghci 中单独使用,那里使用的是什么 monad?

cdk*_*cdk 5

首先,filterPairs为了清楚起见,重写为有针对性的形式:

filterPairs xs = group xs >>= init
Run Code Online (Sandbox Code Playgroud)

我们将能够很好地了解仅从类型中发生了什么。

xs    :: Eq a => [a]
group :: Eq a => [a] -> [[a]]
init  :: [a] -> [a]

(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

第一个参数(>>=)group xs :: [[s]],所以如果我们替换m ~ []and a ~ [s]in(>>=)我们会得到

(>>=) :: [[a]] -> ([a] -> [s]) -> [s]
Run Code Online (Sandbox Code Playgroud)

所以我们使用这里的Monad实例[],它相当于concatMap(检查类型!)。现在我们可以filterPairs再次重写

filterPairs xs = concatMap init (group xs)
Run Code Online (Sandbox Code Playgroud)

现在,如果你弄清楚如何concatMapinitgroup工作,你应该能够人物如何原来的filterPairs作品。