有quite一个 few这里有关于涉及 Monad 的某些类型转换是否可能的问题。
例如,可以创建 f :: Monad m => [m a] -> m [a]
类型的函数。 , 但不可能创建 g :: Monad m => m [a] -> [m a]
类型的函数作为对前者的适当反函数。 (即:f . g = id
)
我想了解可以使用哪些规则来确定是否可以构造该类型的函数,以及如果这些类型不遵守这些规则,为什么不能构造它们。
最佳答案
我一直认为 monad 的方式是 Monad m => m a
类型的值是一些 m
类型的程序执行并生成 a
. monad laws通过将这些程序的组合视为“先做一件事,再做第二件事”来强化这一概念,并产生某种结果组合。
与运行原始程序相同。
m >>= 返回 = m
然后将该值传递给创建新程序的函数,然后
生成的程序应该就像您在
值(value)。
返回 x >>= f = f x
m
,将其结果输入函数 f
生成另一个程序,然后将结果输入第三个函数g
这也产生了一个程序,那么这与创建一个新函数相同,该函数根据 f
的结果返回一个程序进入 g
,并提供 m
的结果进去。(m >>= f) >>= g = m >>= (\x -> f x >>= g)
使用这种关于“创造值(value)的程序”的直觉可以得出一些关于它对您在示例中提供的功能意味着什么的结论。
Monad m => [m a] -> m [a]
偏离这个函数应该做什么的直观定义是困难的:按顺序执行每个程序并收集结果。这会生成另一个程序,该程序会生成结果列表。 Monad m => m [a] -> [m a]
这并没有一个清晰直观的定义,因为它是一个生成列表的程序。如果不访问结果值,则无法创建列表,在这种情况下,这意味着执行程序。某些 monad,它们有一种从程序中提取值的清晰方法,并提供 m a -> a
的一些变体,如 State
monad,可以有一些像这样的功能的健全实现。不过,它必须是特定于应用程序的。其他单子(monad),如 IO
,你无法逃脱。 Monad m => (a -> m b) -> m (a -> b)
这也没有一个清晰直观的定义。这里有一个函数f
生成 m b
类型的程序,但您试图返回 m (a -> b)
类型的函数.基于a
, f
创建具有不同执行语义的完全不同的程序。您不能在 m (a -> b)
类型的单个程序中包含这些变化。 ,即使您可以提供 a -> b
的正确映射在程序结果值。 这种直觉并没有真正完全包含单子(monad)背后的想法。例如,列表的 monadic 上下文实际上并不像程序。
关于haskell - Monads:确定是否可以进行任意转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29568199/