list - Haskell中的Unsequence Monad函数

标签 list function haskell monads reverse

我在设计 Haskell 的 sequence 的反函数时遇到了一些真正的麻烦。功能,Hoogle 告诉我还不存在。这是它的行为方式:

ghci> sequence [Just 7, Just 8, Just 9]
Just [7,8,9]
ghci> sequence [getLine, getLine, getLine]
hey
there
stack exchange
["hey","there","stack exchange"] :: IO [String]

我的问题是制作这样的功能:
unsequence :: (Monad m) => m [a] -> [m a]

所以它的行为是这样的:
ghci> unsequence (Just [7, 8, 9])
[Just 7, Just 8, Just 9]
ghci> sequence getLine
hey
['h','e','y'] :: [IO Char] --(This would actually cause an error, but hey-ho.)

我实际上不知道这是否可能,因为我会在某个时候逃避 monad,但我已经开始了,虽然我不知道如何为这个递归函数设置断点:
unsequence m = (m >>= return . head) : unsequence (m >>= return . tail)

我意识到当 m 时我需要一个断点这里等于 return [] ,但并非所有单子(monad)都有 Eq实例,那么我该怎么做呢?这甚至可能吗?如果是这样,为什么和为什么不呢?请告诉我。

最佳答案

你不能有 unsequence :: (Monad m) => m [a] -> [m a] .问题在于列表:您无法确定列表将包含多少元素,这会使 unsequence 的任何合理定义变得复杂。 .

有趣的是,如果你绝对是, 100% 确保 monad 中的列表是无限的,您可以编写如下内容:

unsequenceInfinite :: (Monad m) => m [a] -> [m a]
unsequenceInfinite x = fmap head x : unsequenceInfinite (fmap tail x)

它会起作用的!

还假设我们有一个 Pair周围的仿函数。我们可以写unsequencePair作为
unsequencePair :: (Monad m) => m (Pair a) -> Pair (m a)
unsequencePair x = Pair (fmap firstPairElement x) (fmap secondPairElement x)

一般来说,事实证明你只能定义 unsequence对于具有属性的仿函数,您可以始终将两个值“压缩”在一起而不会丢失信息。无限列表(在 Haskell 中,一种可能的类型是 Cofree Identity )就是一个例子。 Pair仿函数是另一个。但不是传统的列表,也不是像 Maybe 这样的仿函数或 Either .

distributive 包中,有一个名为 Distributive 的类型类封装了这个属性。您的 unsequence被称为 distribute那里。

关于list - Haskell中的Unsequence Monad函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27342863/

相关文章:

C++ 列表插入迭代器超出范围

python - 根据分数重新排列列表项以适应函数曲线

function - OCaml:函数参数的默认值?

haskell - 为什么我的 Random 实例行为不正确?

haskell - 如何保存

python - 将句子列表连接成短语

sql - PostgreSQL 10 Rowtype 功能错误?

R 将不同的函数应用于不同的数据框列

haskell - Haskell中的Eta减少

list - 如何访问序言中的列表排列?