使用ghci
我已计算:
Prelude> let m = [1,2]
Prelude> let ys = [4, 5, 6]
Prelude> m >>= (\x -> ys >>= (\y -> return (x, y)))
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6)]
上面的monadic表达似乎不符合monad关联法的任何一方:
(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
我想知道monad关联性如何应用于表达式:
m >>= (\x -> ys >>= (\y -> return (x, y)))
因为return (x,y)
关闭了周围的函数和包含它的那个函数,所以在这个例子中,似乎不存在关联性法则(m >>= f)
左侧存在的中间monad。
答案 0 :(得分:7)
我认为你对monadic表达的结构混淆了monadic定律。 monadic associativity法规定,(m >>= f) >>= g
表达式必须等同于m >>= (\x -> f x >>= g)
的表达式m
才能被视为monad。
这并不意味着每个monadic表达式必须是(m >>= f) >>= g
形式。
例如,m >>= f
是完全有效的monadic表达式,即使它不是(m >>= f) >>= g
形式。然而,它仍然遵守monadic相关性法则,因为m
可以扩展到m >>= return
(来自monadic权利身份法m >>= return ≡ m
)。因此:
m >>= f
-- is equivalent to
(m >>= return) >>= f
-- is of the form
(m >>= f) >>= g
在您的示例中,m >>= (\x -> ys >>= (\y -> return (x, y)))
的格式为m >>= f
,其中f
为\x -> ys >>= (\y -> return (x, y))
。
虽然\x -> ys >>= (\y -> return (x, y))
不是\x -> f x >>= g
形式(来自monadic associativity law的右侧),但并不意味着它违反了monadic定律。
通过将m >>= (\x -> ys >>= (\y -> return (x, y)))
替换为m >>= return
,表达式m
可以扩展为monadic关联形式:
(m >>= return) >>= (\x -> ys >>= (\y -> return (x, y)))
-- is of the form
(m >>= f) >>= g
-- and can be written as
m >>= (\x -> return x >> (\x -> ys >>= (\y -> return (x, y))))
希望澄清事情。
答案 1 :(得分:3)
实际上,由于原始表达式中x
的范围,因此不可能直接应用关联法则:
import Control.Monad (liftM)
test = let m = [1,2]
ys = [4, 5, 6]
in m >>= (\x -> ys >>= (\y -> return (x, y)))
但是,如果我们将它包含在第一个monadic计算的结果中,我们可以缩小x
的范围。我们不会在[Int]
中返回x -> ys
,而是使用\x -> liftM ((,) x) ys
并返回[(Int,Int)]
,其中每对中的第一个数字始终为x
,第二个数字为ys
liftM
之一。 (请注意,对于列表map
与x
相同。)第二个函数将从其输入中读取test1 = let m = [1,2]
ys = [4, 5, 6]
in m >>= (\x -> liftM ((,) x) ys >>= (\(x', y) -> return (x', y)))
的值:
\(x', y) -> return (x', y)
(monadic函数return
现在可以简化为>>= return
,随后test2 = let m = [1,2]
ys = [4, 5, 6]
in (m >>= \x -> liftM ((,) x) ys) >>= (\(x, y) -> return (x, y))
被完全删除,但是为了参数,让它保留在那里。)
现在每个monadic函数都是自包含的,我们可以应用关联性法则:
{{1}}
答案 2 :(得分:1)
monadic法仅适用于一个参数的功能。表达式
xs >>= (\x -> ys >>= (\y -> (x, y)))
实际上相当于:
xs >>= \x -> fmap ($ x) $ ys >>= \y -> return (\x -> (x,y))
(如果我们要避免捕获x
)
因此,您无法应用相同的法律 - 我们在关联法律中fmap
为f
而g
没有xs >>= \x -> fmap ($ x) $ fmap (\y x -> (x,y)) ys
。
以上内容当然与:
相同xs >>= \x -> fmap (\y -> (x,y)) ys
或
{{1}}