我正在尝试创建一个将状态和错误处理结合在一起的monad,
import Control.Monad
data Result a e = Ok a | Error e
newtype StateError s e a = StateError { runStateError :: s -> (Result a e, s) }
instance Monad (StateError s e) where
return x = StateError $ \s -> (Ok x, s)
m >>= f = StateError $
\s -> case runStateError m s of
(Ok x, s') -> runStateError (f x) s'
e -> e
get = StateError $ \s -> ((Ok s), s)
put s = StateError $ \_ -> ((Ok ()), s)
main = return ()
编译时,我收到此错误,我不知道如何解决:
StateError.hs:13:18: error:
• Couldn't match type ‘a’ with ‘b’
‘a’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b.
StateError s e a -> (a -> StateError s e b) -> StateError s e b
at StateError.hs:10:5-7
‘b’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b.
StateError s e a -> (a -> StateError s e b) -> StateError s e b
at StateError.hs:10:5-7
Expected type: (Result b e, s)
Actual type: (Result a e, s)
• In the expression: e
In a case alternative: e -> e
In the expression:
case runStateError m s of
(Ok x, s') -> runStateError (f x) s'
e -> e
• Relevant bindings include
e :: (Result a e, s) (bound at StateError.hs:13:13)
f :: a -> StateError s e b (bound at StateError.hs:10:9)
m :: StateError s e a (bound at StateError.hs:10:3)
(>>=) :: StateError s e a
-> (a -> StateError s e b) -> StateError s e b
(bound at StateError.hs:10:5)
|
13 | e -> e
| ^
我在这里做错了什么?我认为问题在于难以匹配case
Expected type: (Result b e, s)
Actual type: (Result a e, s)
喜欢强制a
成为b
或类似的东西,但是我不知道如何解决这个问题。
此外,我也收到此错误:
StateError.hs:7:10: error:
• No instance for (Applicative (StateError s e))
arising from the superclasses of an instance declaration
• In the instance declaration for ‘Monad (StateError s e)’
|
7 | instance Monad (StateError s e) where
| ^^^^^^^^^^^^^^^^^^^^^^
这要求我实例化Applicative
,因此,我希望您能从此处获得一些指导。
谢谢
答案 0 :(得分:3)
通过将代码更改为
,可以修复您的错误。 m >>= f = StateError $
\s -> case runStateError m s of
(Ok x, s1) -> runStateError (f x) s1
(Error e, s1) -> (Error e, s1)
-- or:
-- (Error e, s1) -> (Error e, s) -- also works
-- not:
-- e -> e -- this doesn't
和adding明显的Functor
和Applicative
实例,
instance Functor .... where
fmap = liftM
instance Applicative .... where
(<*>) = ap
pure = return
Error e :: Result a e
是多态的,
data Result a e = Ok a | Error e
因此在该箭头的左侧和右侧具有不同的类型。由于它在错误消息中抱怨,
Expected type: (Result b e, s)
Actual type: (Result a e, s)
当您使用变量时,这使得箭头两侧的相同相同。因此e
重用了相同的值,但是Error e
根据需要创建了适当类型的新值。而且我们确实需要(>>=)
签名所要求的新类型:
Monad m => m a -> (a -> m b) -> m b
-- ^^ ^^