liftM 函数是否剥夺了它们的单子本质?
Are the liftM functions deprived of their monadic essence?
monad和applicative的区别在于前者可以根据之前的结果选择下一次计算:
(\x -> if x == 1 then (\_ -> []) else (\y -> (\z -> \w -> [x,y,z]) =<< sqr) =<< (+1)) =<< (+1) $ 0
-- ^
(\w x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) <*> (+1) <*> (+1) <*> sqr $ 0
-- ^^^
一元计算可以使计算短路,而对于应用计算,我们必须使用整个计算结构和 运行 所有效果,无论我们提供什么输入。
让我们将其与 liftM
进行比较:
liftM3 (\x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) (+1) (+1) sqr $ 0
-- ^^^
这似乎是变相的应用风格。即使我用 monadic applicator 替换 lift 运算符,整个结构似乎也失去了它的 monadic 属性:
appM3 w f x g y h z =
f(\x' -> g(\y' -> h(\z' -> w x' y' z') z) y) x
appM3 (\x -> if x == 1 then (\_ _ _ -> []) else (\y z _ -> [x, y, z])) (=<<) (+1) (=<<) (+1) (=<<) sqr $ 0
-- ^^^^^
这是否意味着正确的一元计算必须始终手动编码?我知道 do 符号,但底层机制似乎类似于宏扩展(如果这是废话,请纠正我),所以它并没有真正反驳我的假设。
你是对的。 liftM
就是 fmap
,liftM2
就是 liftA2
。它们的存在是标准库中仍然僵化的历史产物,而不是真正需要 monadic bind 操作的力量的东西。
以前版本的标准库没有使 Functor
和 Applicative
超越 Monad
的 类。 (如果你回溯得足够远,Applicative
甚至不存在。)所以为了实用性,创建了做同样事情的函数以与 Monad
一起使用。它们在 Applicative-Monad 提案的过渡中幸存下来,因为它们对一个目的仍然有用 - 如果您手动实现所有 类,您可以使用它们来实现类型的 Functor
和 Applicative
根据 Monad
代码的实例。
monad和applicative的区别在于前者可以根据之前的结果选择下一次计算:
(\x -> if x == 1 then (\_ -> []) else (\y -> (\z -> \w -> [x,y,z]) =<< sqr) =<< (+1)) =<< (+1) $ 0
-- ^
(\w x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) <*> (+1) <*> (+1) <*> sqr $ 0
-- ^^^
一元计算可以使计算短路,而对于应用计算,我们必须使用整个计算结构和 运行 所有效果,无论我们提供什么输入。
让我们将其与 liftM
进行比较:
liftM3 (\x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) (+1) (+1) sqr $ 0
-- ^^^
这似乎是变相的应用风格。即使我用 monadic applicator 替换 lift 运算符,整个结构似乎也失去了它的 monadic 属性:
appM3 w f x g y h z =
f(\x' -> g(\y' -> h(\z' -> w x' y' z') z) y) x
appM3 (\x -> if x == 1 then (\_ _ _ -> []) else (\y z _ -> [x, y, z])) (=<<) (+1) (=<<) (+1) (=<<) sqr $ 0
-- ^^^^^
这是否意味着正确的一元计算必须始终手动编码?我知道 do 符号,但底层机制似乎类似于宏扩展(如果这是废话,请纠正我),所以它并没有真正反驳我的假设。
你是对的。 liftM
就是 fmap
,liftM2
就是 liftA2
。它们的存在是标准库中仍然僵化的历史产物,而不是真正需要 monadic bind 操作的力量的东西。
以前版本的标准库没有使 Functor
和 Applicative
超越 Monad
的 类。 (如果你回溯得足够远,Applicative
甚至不存在。)所以为了实用性,创建了做同样事情的函数以与 Monad
一起使用。它们在 Applicative-Monad 提案的过渡中幸存下来,因为它们对一个目的仍然有用 - 如果您手动实现所有 类,您可以使用它们来实现类型的 Functor
和 Applicative
根据 Monad
代码的实例。