【发布时间】:2020-04-23 11:16:15
【问题描述】:
我偶然发现的问题与 >>= 应用程序对这样的示例类型有关:
data ThreeArgs a = ThreeArgs a a a deriving (Show,Eq)
instance Functor ThreeArgs where
fmap f (ThreeArgs a b c) = ThreeArgs (f a) (f b) (f c)
instance Applicative ThreeArgs where
pure x = ThreeArgs x x x
(ThreeArgs a b c) <*> (ThreeArgs p s q) = ThreeArgs (a p) (b s) (c q)
我会声明一个 Monad 实例如下:
instance Monad ThreeArgs where
return x = ThreeArgs x x x
(ThreeArgs a b c) >>= f = f ... -- a code I need to complete
是的,看起来f 似乎应用于所有三个ThreeArgs 构造函数参数。如果我完成最后一行
(ThreeArgs a b c) >>= f = f a
那么编译器没有任何抱怨,而结果是:
*module1> let x = do { x <- ThreeArgs 1 2 3; y <- ThreeArgs 4 6 7; return $ x + y }
*module1> x
ThreeArgs 5 5 5
这意味着求和会导致具有相同参数值的上下文,尽管正确的输出应该是ThreeArgs 5 8 10。一旦我编辑到
(ThreeArgs a b c) >>= f = (f a) (f b) (f c)
编译器警报:
Couldn't match expected type `ThreeArgs b
-> ThreeArgs b -> ThreeArgs b -> ThreeArgs b'
with actual type `ThreeArgs b'
所以,我看到一个严重的错误指导了我的理解,但我仍然很难理解 Haskell 中的单子类和其他类似的东西。大概,我想在这里使用递归还是其他什么?
【问题讨论】:
-
我不能肯定地说,但我的直觉是没有“明智的” Monad 实例(一个使用所有 3 个包含值的实例,特别是一个给出您打算用于该示例的结果的实例)这种类型是可能的。您对类型应该代表什么有任何见解吗?您是否已经创建了
Functor和Applicative实例? -
我已经为 Functor 和 Applicative 的实例添加了一些代码。要管理这个问题,以便在输入
do { x <- ThreeArgs 1 2 3; y <- ThreeArgs 4 6 7; return $ x + y }后程序运行到ThreeArgs 5 8 10。 -
谢谢,这些实例符合我的预期,但只是想确认一下。我认为这里没有 Monad 实例的原因是您的类型现在基本上是 ZipList 限制为只有 3 个元素。
ZipList没有 Monad 实例(尽管我不知道如何证明永远不可能存在)。此外,我希望将元素限制在 3 个以内会使实例变得更加困难,而不是更容易。 -
@tex 但是所有三个值的类型都是
a。Functor实例很好。fmap id (ThreeArgs a b c) == ThreeArgs a b c和fmap (f . g) (ThreeArgs a b c) == ThreeArgs (f (g a)) (f (g b)) (f (g c)) == fmap f (ThreeArgs (g a) (g b) (g c))。 -
@RobinZigmond 实际上,限制确实让事情变得更容易,因为它将不可能变为可能。
标签: haskell functional-programming monads