- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
众所周知,应用仿函数在组合下是封闭的,但 monad 不是。然而,我一直很难找到一个具体的反例来表明单子(monad)并不总是组合的。
This answer给出 [String -> a]
作为非 monad 的示例。经过一番尝试后,我凭直觉相信它,但这个答案只是说“连接无法实现”,而没有真正给出任何理由。我想要更正式的东西。当然,有很多类型为 [String -> [String -> a]] -> [String -> a]
的函数;必须证明任何这样的函数必然不满足单子(monad)定律。
任何例子(附带证明)都可以;我不一定要特别寻找上述示例的证明。
最佳答案
考虑这个与 (Bool ->)
同构的 monad单子(monad):
data Pair a = P a a
instance Functor Pair where
fmap f (P x y) = P (f x) (f y)
instance Monad Pair where
return x = P x x
P a b >>= f = P x y
where P x _ = f a
P _ y = f b
并用 Maybe
组成它单子(monad):
newtype Bad a = B (Maybe (Pair a))
我声称Bad
不能是单子(monad)。
部分证明:
只有一种方法可以定义 fmap
满足fmap id = id
:
instance Functor Bad where
fmap f (B x) = B $ fmap (fmap f) x
回想一下单子(monad)定律:
(1) join (return x) = x
(2) join (fmap return x) = x
(3) join (join x) = join (fmap join x)
对于return x
的定义,我们有两个选择:B Nothing
或B (Just (P x x))
。很明显,为了有任何返回的希望x
从(1)和(2),我们不能扔掉x
,所以我们必须选择第二个选项。
return' :: a -> Bad a
return' x = B (Just (P x x))
剩下 join
。由于只有几个可能的输入,我们可以为每个输入提供一个案例:
join :: Bad (Bad a) -> Bad a
(A) join (B Nothing) = ???
(B) join (B (Just (P (B Nothing) (B Nothing)))) = ???
(C) join (B (Just (P (B (Just (P x1 x2))) (B Nothing)))) = ???
(D) join (B (Just (P (B Nothing) (B (Just (P x1 x2)))))) = ???
(E) join (B (Just (P (B (Just (P x1 x2))) (B (Just (P x3 x4)))))) = ???
由于输出的类型为 Bad a
,唯一的选项是 B Nothing
或B (Just (P y1 y2))
哪里y1
, y2
必须从x1 ... x4
中选择.
在情况 (A) 和 (B) 中,我们没有 a
类型的值,所以我们被迫返回B Nothing
在这两种情况下。
情况 (E) 由 (1) 和 (2) 单子(monad)定律确定:
-- apply (1) to (B (Just (P y1 y2)))
join (return' (B (Just (P y1 y2))))
= -- using our definition of return'
join (B (Just (P (B (Just (P y1 y2))) (B (Just (P y1 y2))))))
= -- from (1) this should equal
B (Just (P y1 y2))
为了返回B (Just (P y1 y2))
在情况 (E) 中,这意味着我们必须选择 y1
来自 x1
或x3
,和y2
来自 x2
或x4
.
-- apply (2) to (B (Just (P y1 y2)))
join (fmap return' (B (Just (P y1 y2))))
= -- def of fmap
join (B (Just (P (return y1) (return y2))))
= -- def of return
join (B (Just (P (B (Just (P y1 y1))) (B (Just (P y2 y2))))))
= -- from (2) this should equal
B (Just (P y1 y2))
同样,这表示我们必须选择 y1
来自 x1
或x2
,和y2
来自 x3
或x4
。结合两者,我们确定 (E) 的右侧必须是 B (Just (P x1 x4))
.
到目前为止,一切都很好,但是当您尝试填写 (C) 和 (D) 的右侧时,问题就出现了。
每个都有 5 个可能的右侧,但没有一个组合有效。我对此还没有一个很好的论据,但我确实有一个程序可以详尽地测试所有组合:
{-# LANGUAGE ImpredicativeTypes, ScopedTypeVariables #-}
import Control.Monad (guard)
data Pair a = P a a
deriving (Eq, Show)
instance Functor Pair where
fmap f (P x y) = P (f x) (f y)
instance Monad Pair where
return x = P x x
P a b >>= f = P x y
where P x _ = f a
P _ y = f b
newtype Bad a = B (Maybe (Pair a))
deriving (Eq, Show)
instance Functor Bad where
fmap f (B x) = B $ fmap (fmap f) x
-- The only definition that could possibly work.
unit :: a -> Bad a
unit x = B (Just (P x x))
-- Number of possible definitions of join for this type. If this equals zero, no monad for you!
joins :: Integer
joins = sum $ do
-- Try all possible ways of handling cases 3 and 4 in the definition of join below.
let ways = [ \_ _ -> B Nothing
, \a b -> B (Just (P a a))
, \a b -> B (Just (P a b))
, \a b -> B (Just (P b a))
, \a b -> B (Just (P b b)) ] :: [forall a. a -> a -> Bad a]
c3 :: forall a. a -> a -> Bad a <- ways
c4 :: forall a. a -> a -> Bad a <- ways
let join :: forall a. Bad (Bad a) -> Bad a
join (B Nothing) = B Nothing -- no choice
join (B (Just (P (B Nothing) (B Nothing)))) = B Nothing -- again, no choice
join (B (Just (P (B (Just (P x1 x2))) (B Nothing)))) = c3 x1 x2
join (B (Just (P (B Nothing) (B (Just (P x3 x4)))))) = c4 x3 x4
join (B (Just (P (B (Just (P x1 x2))) (B (Just (P x3 x4)))))) = B (Just (P x1 x4)) -- derived from monad laws
-- We've already learnt all we can from these two, but I decided to leave them in anyway.
guard $ all (\x -> join (unit x) == x) bad1
guard $ all (\x -> join (fmap unit x) == x) bad1
-- This is the one that matters
guard $ all (\x -> join (join x) == join (fmap join x)) bad3
return 1
main = putStrLn $ show joins ++ " combinations work."
-- Functions for making all the different forms of Bad values containing distinct Ints.
bad1 :: [Bad Int]
bad1 = map fst (bad1' 1)
bad3 :: [Bad (Bad (Bad Int))]
bad3 = map fst (bad3' 1)
bad1' :: Int -> [(Bad Int, Int)]
bad1' n = [(B Nothing, n), (B (Just (P n (n+1))), n+2)]
bad2' :: Int -> [(Bad (Bad Int), Int)]
bad2' n = (B Nothing, n) : do
(x, n') <- bad1' n
(y, n'') <- bad1' n'
return (B (Just (P x y)), n'')
bad3' :: Int -> [(Bad (Bad (Bad Int)), Int)]
bad3' n = (B Nothing, n) : do
(x, n') <- bad2' n
(y, n'') <- bad2' n'
return (B (Just (P x y)), n'')
关于haskell - 具体的例子表明单子(monad)在组合下不是封闭的(有证明)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13034229/
是否有一种标准方法可以表明 R 包是专有的,归公司所有,不应在公司外部共享?现在,我在 DESCRIPTION 中使用它文件: License: Proprietary, ownership of X
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我有一个方法可以根据 3 个正则表达式验证字段并根据失败的表达式返回错误。 function mfpValidateValue() { var pCtrl = window.document.
这个问题已经有答案了: Order of from and to values in SQL Between (3 个回答) 已关闭 4 年前。 我正在尝试从 leads 获取上周的数据表但是当我使用
我正在编写一个 pygame 代码来制作汽车游戏。这是一款基本的汽车游戏,英雄 Sprite 汽车应该避免与敌方 Sprite 接触。因此,对于碰撞部分,我们必须为敌车和英雄车创建一个 mask 。
我有一个情况,当满足某些条件时,该集团根本不产生任何状态(忽略所有事件)。当向bloc添加新事件时,如何测试没有状态产生? 我正在使用 flutter_bloc:^ 3.1.0 和 bloc_test
当我运行包含NAudio库的程序时,出现以下错误,“由于其保护级别而无法访问”。 public void ReadWaveHeader(Stream stream) { this.dataCh
Closed. This question needs details or clarity。它当前不接受答案。 想改善这个问题吗?添加详细信息,并通过editing this post阐明问题。 9
如果我运行以下命令: from dateutil import parser parser.parse("Wind10_463@Y2014_M11_D19", fuzzy=True) 我明白了: da
我正在尝试解决第 6 章 - 点定位的“计算几何算法和应用,第 3 版 - de berg 等人”一书的一些练习。不幸的是,我不知道如何解决以下练习: Given a convex polygon P
我是一名优秀的程序员,十分优秀!