我使用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]]
答案 0 :(得分:9)
首先,我要注意:您可以将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}}必须 a
和return 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
。