【发布时间】:2017-01-04 03:36:02
【问题描述】:
这是我的代码。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module StateParser where
import Control.Monad
import Control.Applicative
newtype State s a = State {compute :: s -> (a, s)}
newtype StateM m s a = StateM {compute_M :: s -> m (a, s)}
result_s :: a -> State s a
result_s v = State (\s -> (v ,s))
bind_s :: State s a -> (a -> State s b) -> State s b
bind_s st f = State $ \s -> (\(v, s') -> compute (f v) s') (compute st s)
result_sm :: (Functor m) => a -> StateM m s a
result_sm v = StateM (\s -> result_s (v, s))
bind_sm :: (Functor m) => StateM m s a -> (a -> StateM m s b) -> StateM m s b
bind_sm stm f = StateM $ \s -> (tmp s `bind_sm` id)
where
tmp s = fmap (\(v, s') -> compute_M (f v) s') (compute_M stm s)
instance Functor (State s) where
fmap f st = st >>= (pure . f)
instance Applicative (State s) where
pure = result_s
p <*> q = p >>= \f ->
q >>= (pure . f)
instance Monad (State s) where
--Explicit return definition only required for code required to be compatible
--with GHC versions prior to 7.10. The default implementation for all GHC
--versions from 7.10 is
return = pure
(>>=) = bind_s
instance Functor f => Functor (StateM f s) where
fmap f stm = stm `bind_sm` (result_sm . f)
instance Applicative f => Applicative (StateM f s) where
pure = result_sm
p <*> q = p `bind_sm` \f ->
q `bind_sm` (pure . f)
instance Monad m => Monad (StateM m s) where
return = pure
(>>=) = bind_sm
编译时出现 2 个类型不匹配错误:
StateParser.hs:43:29
Couldn't match type `m' with `State s1'
`m' is a rigid type variable bound by
the type signature for result_sm :: Functor m => a -> StateM m s a
at StateParser.hs:42:14
Expected type: m (a, s)
Actual type: State s1 (a, s)
...
In the expression: result_s (v, s)
In the first argument of `StateM', namely
`(\ s -> result_s (v, s))'
StateParser.hs:46:33:
Couldn't match type `m' with `StateM m0 s0'
`m' is a rigid type variable bound by
the type signature for
bind_sm :: Functor m =>
StateM m s a -> (a -> StateM m s b) -> StateM m s b
at StateParser.hs:45:12
Expected type: StateM m0 s0 (m (b, s))
Actual type: m (m (b, s))
...
In the first argument of `bind_sm', namely `tmp s'
In the expression: (tmp s `bind_sm` id)
但是,我已经为类型构造函数State s 和StateM f s 非常明确地定义了Functor 类型类的实例,这应该允许它们与类型变量m 匹配,由Functor 类型类绑定在bind_sm 和result_sm。
我可能不知道 Haskell 的类型推断过程的某些方面。有人能启发我吗?
【问题讨论】:
-
这里没有魔法发生——你的函数完全是错误的(类型不正确),类型检查器完全正确地拒绝它。由于编译器已经准确地告诉你程序为什么不正确,你是否尝试过修复它告诉你错误的东西? (你读过错误吗?)至少,
StateM $ \s -> .. `bind_sm` ..意味着StateM应该有类型s -> StateM m0 x0 (StateM m1 x1 (a,s)),它显然没有。
标签: haskell types functional-programming type-conversion