我用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"
Run Code Online (Sandbox Code Playgroud)
这个地图很容易理解,但是,我觉得unjoin . join = id应该存在但是没有在搜索中找到它[a] -> [[a]]
首先我想说明:您可以查看您map (:[])的map return的名单单子.
join :: m (m a) -> m a例如,该函数不是单射的
join ["abc","def"]join ["ab","cdef"]有相同的形象.同样的问题是与其他monad:
join (Just Nothing)join Nothing因此通常不存在反函数.
但现在我们知道没有左逆可以存在.
在所有情况下你都有
join . return = id.
Run Code Online (Sandbox Code Playgroud)
我认为 - 但尚未证实,同样适用
join . fmap return = id.
Run Code Online (Sandbox Code Playgroud)
(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
Run Code Online (Sandbox Code Playgroud)
现在我们可以应用eta减少(这只是一个很容易放弃的词x)并获得
join . return = id
Run Code Online (Sandbox Code Playgroud)
注意:id这是m a -> m a!
为了使事情具体化 - 让我们在列表monad中进行此计算[a].
(join . return) "wizzup" = join (return "(^ ? ^)") -- return = \x -> [x]
-- and join = foldl (++) []
= foldl (++) [] ["(^ ? ^)"]
= "(^ ? ^)"
Run Code Online (Sandbox Code Playgroud)
这里的版本 (join . fmap return)
(join . fmap return) "(^ ? ^)" = (foldl (++) [] . map (\x -> [x]))"(^ ? ^)"
= foldl (++) [] ["(","^"," ? ","^",")"]
= "(^ ? ^)"
Run Code Online (Sandbox Code Playgroud)
没有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的,因为unjoin会知道它的输入的每一个元素可以在一个单一的列表被包裹(这是想要map return做在列表monad).
根据以下方式编写的三个monad法律join是:
join . return = id
join . fmap return = id
join . join = join . fmap join
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这可以保证return与join您正在寻找的相反.
实际上,map (:[]) = map return = fmap return它也是一个正确的反转join.
请注意,这意味着在任何monad中join 都不能有左反,其中return /= fmap return:
假设return /= fmap return,对于一些monad.再有就是一些动作a,这样
return a /= fmap return a
Run Code Online (Sandbox Code Playgroud)
但
join (return a) = a = join (fmap return a)
Run Code Online (Sandbox Code Playgroud)
你的unjoin,适用于a,必须是既 return a与fmap return a(和可能更多的值),这是一个矛盾.
请注意,对于[]:
return [x, y] = [[x, y]]
fmap return [x, y] = [[x], [y]]
Run Code Online (Sandbox Code Playgroud)
用于IO:
Prelude> return (print "Hello") :: IO (IO ())
Prelude> fmap return (print "Hello") :: IO (IO ())
"Hello"
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一的monad是哪里return和fmap return重合的Identity.