如何在 Haskell 中使用 Monad class 将函数映射到多个构造函数参数?
How to map a function over multiple constructor arguments working with Monad class in Haskell?
我遇到的问题与 >>=
应用到这样的样本类型有关:
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'
所以,我看到一个严重的错误指导了我的理解,但我仍然很难理解 monadic class 和 Haskell 中的其他类似东西。据推测,我是想在这里使用递归还是其他什么?
ThreeArgs
与 ((->) Ordering)
同构。见证人:
to :: ThreeArgs a -> Ordering -> a
to (ThreeArgs x _ _) LT = x
to (ThreeArgs _ y _) EQ = y
to (ThreeArgs _ _ z) GT = z
from :: (Ordering -> a) -> ThreeArgs a
from f = ThreeArgs (f LT) (f EQ) (f GT)
您的 Functor
和 Applicative
实例与 ((->) r)
的实例匹配,因此我们可以使其与 its Monad
one 的实例匹配,我们就完成了.
instance Monad ThreeArgs where
ThreeArgs x y z >>= f = ThreeArgs x' y' z' where
ThreeArgs x' _ _ = f x
ThreeArgs _ y' _ = f y
ThreeArgs _ _ z' = f z
顺便说一句,像 ThreeArgs
这样的数据结构的通用术语是 "representable functor",如果您想了解更多相关信息。
我遇到的问题与 >>=
应用到这样的样本类型有关:
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'
所以,我看到一个严重的错误指导了我的理解,但我仍然很难理解 monadic class 和 Haskell 中的其他类似东西。据推测,我是想在这里使用递归还是其他什么?
ThreeArgs
与 ((->) Ordering)
同构。见证人:
to :: ThreeArgs a -> Ordering -> a
to (ThreeArgs x _ _) LT = x
to (ThreeArgs _ y _) EQ = y
to (ThreeArgs _ _ z) GT = z
from :: (Ordering -> a) -> ThreeArgs a
from f = ThreeArgs (f LT) (f EQ) (f GT)
您的 Functor
和 Applicative
实例与 ((->) r)
的实例匹配,因此我们可以使其与 its Monad
one 的实例匹配,我们就完成了.
instance Monad ThreeArgs where
ThreeArgs x y z >>= f = ThreeArgs x' y' z' where
ThreeArgs x' _ _ = f x
ThreeArgs _ y' _ = f y
ThreeArgs _ _ z' = f z
顺便说一句,像 ThreeArgs
这样的数据结构的通用术语是 "representable functor",如果您想了解更多相关信息。