是否有 Control.Monad 的内置 "inverse function" 连接?
Is there a builtin "inverse function" of Control.Monad's join?
我使用 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
应该存在,但是在hoogle搜索中没有找到[a] -> [[a]]
TL;DR - 不,没有这样的功能
首先我要注意:您可以将 map (:[])
视为列表 monad 的 map return
。
解释为什么不存在这样的功能(以合理的方式)
函数join :: m (m a) -> m a
不是单射的,例如
join ["abc","def"]
join ["ab","cdef"]
有相同的图像。其他单子也有同样的问题:
join (Just Nothing)
join Nothing
所以一般来说反函数是不存在的。
但现在我们知道不存在左逆。
右逆呢?
在所有情况下你有
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 (++) [] ["(","^"," ͜ ","^",")"]
= "(^ ͜ ^)"
根据 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
应用于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
重合的唯一单子是 Identity
.
没有函数 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
会知道
它的输入的每个元素都可以包装在一个列表中(这是 want map return
在列表 monad 中做的)。
我使用 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
应该存在,但是在hoogle搜索中没有找到[a] -> [[a]]
TL;DR - 不,没有这样的功能
首先我要注意:您可以将 map (:[])
视为列表 monad 的 map return
。
解释为什么不存在这样的功能(以合理的方式)
函数join :: m (m a) -> m a
不是单射的,例如
join ["abc","def"]
join ["ab","cdef"]
有相同的图像。其他单子也有同样的问题:
join (Just Nothing)
join Nothing
所以一般来说反函数是不存在的。
但现在我们知道不存在左逆。
右逆呢?
在所有情况下你有
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 (++) [] ["(","^"," ͜ ","^",")"]
= "(^ ͜ ^)"
根据 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
应用于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
重合的唯一单子是 Identity
.
没有函数 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
会知道
它的输入的每个元素都可以包装在一个列表中(这是 want map return
在列表 monad 中做的)。