【发布时间】:2020-01-31 10:18:20
【问题描述】:
据我所知,函子是那些有map() 的,而单子是那些也有flatMap() 的。
所有的 Monad 都是 Functor,但反之则不然。是什么阻止了 Functor 实现 flatMap() 并成为 Monad?
由于某些限制,是否有任何函子保持这种状态。你能提供一些例子吗?谢谢。
【问题讨论】:
标签: java haskell functional-programming monads vavr
据我所知,函子是那些有map() 的,而单子是那些也有flatMap() 的。
所有的 Monad 都是 Functor,但反之则不然。是什么阻止了 Functor 实现 flatMap() 并成为 Monad?
由于某些限制,是否有任何函子保持这种状态。你能提供一些例子吗?谢谢。
【问题讨论】:
标签: java haskell functional-programming monads vavr
all monads are functors 的意思是,只使用 Monad 的方法,我们就可以实现 Functor 的方法。这确实可以做到,这就是为什么我们说所有的单子都是函子。我不知道 Vavr,但这是 Haskell 中的一些代码:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
instance Monad m => Functor m where
fmap f x = x >>= (\x' -> return (f x'))
相比之下,all functors are monads这句话意味着,仅使用 Functor 中的方法,我们就可以实现 Monad 中的方法。这是做不到的,因为你可以用 monad 做一些你不能用 functor 做的事情。所以我们说并不是所有的函子都是单子。
【讨论】:
Functor m 的非法实例声明”。 repl.it/repls/TiredThunderousMigration
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 是这种实例声明所必需的。这些是非常常见的语言扩展,您实际上会在(我估计)所有 Haskell 源文件的一半上找到它们。 (但即使有这些扩展,如果你编写那个实例,它当然会出错,因为它与直接声明的 Functor 实例冲突。)
monad_fmap :: Monad m => (a -> b) -> m a -> m b,并实现它而不是fmap。
monad_fmap 又名liftM。 :)
如果一个类型实现了flatMap()(以及return()/unit()/emit()/inject()/wrap()/...),根据定义,它已经是一个Monad。
“函子”是给定类型的非常狭窄的视图。它只考虑其map() 的能力。当将其视为“函子”的实例时,不考虑给定类型的任何细节。
如果给定类型可以实现守法(*)flatMap()(以及return()),那么它也可以被视为“Monad”的合法实例。
如果一个 opaque 类型没有为我们提供return(),它就不能被视为 Monad,这是一种可能性。
另一个是flatMap(),它不遵循单子定律。
edit: (*) 感谢@leftaroundabout 指出法律。另一方面,在 Haskell 中声明一个非法的 Monad 实例在技术上仍然是可行的,尽管这肯定是不可取的。
【讨论】: