是否存在Control.Monad加入的内置“反函数”?

时间:2016-04-27 13:41:47

标签: haskell monads

我使用map (:[])String拆分为[[Char]]并想知道是否有任何内置函数存在同样存在

In [1]: as = "abcdefg"

In [2]: bs = map (:[]) as
        print bs
        ["a","b","c","d","e","f","g"]

In [3]: import Control.Monad
        cs = join bs
        print cs
        "abcdefg"

这张地图很容易理解,不过,我觉得unjoin . join = id应该存在,但在搜索中找不到[a] -> [[a]]

3 个答案:

答案 0 :(得分:9)

TL; DR - 没有这样的功能

首先,我要注意:您可以将map (:[])视为列表monad的map return

解释为什么不存在这样的功能(以合理的方式)

函数join :: m (m a) -> m a不是单射的,例如

  • join ["abc","def"]
  • join ["ab","cdef"]

拥有相同的图像。同样的问题是与其他monad:

  • join (Just Nothing)
  • join Nothing

因此通常不存在反函数。

但现在我们知道不存在 left-inverse

右反过来怎么样?

在所有情况下你都有

join . return = id.

我认为 - 但尚未证明,

同样如此
join . fmap return = id.

证明。

(join . return) x =  join (return x) -- with the definition of join
                  = return x >>= id -- with monad laws (https://wiki.haskell.org/Monad_laws 
                  = id x

现在我们可以应用eta减少(这只是放弃x的一个很好的词)并获得

join . return = id

注意:id此处为m a -> m a

为了使事情具体化 - 让我们在列表monad [a]中进行此计算。

(join . return) "wizzup" = join (return "(^ ͜ ^)") -- return = \x -> [x]
                                                  -- and join = foldl (++) []
                         = foldl (++) [] ["(^ ͜ ^)"]
                         = "(^ ͜ ^)"

此处为(join . fmap return)

的版本
(join . fmap return) "(^ ͜ ^)" = (foldl (++) [] . map (\x -> [x]))"(^ ͜ ^)"
                              = foldl (++) [] ["(","^"," ͜ ","^",")"]
                              = "(^ ͜ ^)"

答案 1 :(得分:6)

没有unjoin函数unjoin . join == id。假设join x评估为["abc"]。现在,x是什么unjoin . join $ x == x?是["a", "b", "c"]吗?是["ab", "c"]吗?是["a", "bc"]吗?或者它是无限多列表之一,如["a", "", "bc"](在有限字符串中出现空字符串)?将join应用于该值后,您将丢失恢复原始值所需的信息。

如果join仅限于一个字符的列表(没有多字符串,没有空字符串),那么您确实可以unjoin定义unjoin . join x == x,因为{{ 1}}会知道 它的输入的每个元素都可以包装在一个列表中(列表monad中需要unjoin)。

答案 2 :(得分:5)

根据join编写的三个monad法律是:

join . return = id
join . fmap return = id
join . join = join . fmap join

如您所见,这可以保证return与您正在寻找的join相反。

实际上,map (:[]) = map return = fmap return 也是 join的右逆。

请注意,这意味着join 不能左侧反转,在return /= fmap return的任何单子中:

假设return /= fmap return,对于某些monad。然后有一些动作a,以便

return a /= fmap return a

join (return a) = a = join (fmap return a)

适用于unjoin的{​​{1}}必须 areturn a(可能还有更多值),这是矛盾。

请注意,对于fmap return a

[]

return [x, y] = [[x, y]] fmap return [x, y] = [[x], [y]]

IO

等。我能想到Prelude> return (print "Hello") :: IO (IO ()) Prelude> fmap return (print "Hello") :: IO (IO ()) "Hello" return重合的唯一单身是fmap return