为什么我会遇到类型不匹配错误?

时间:2016-08-27 17:02:03

标签: haskell types functional-programming type-conversion

这是我的代码。

{-# 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)

但是,我已经非常清楚地定义了类型构造函数FunctorState s的{​​{1}}类型类的实例,它们应该允许它们与类型变量StateM f s匹配,受mFunctorbind_sm类型类的约束。

Haskell的类型推断过程可能有些方面我不知道。有人会启发我吗?

1 个答案:

答案 0 :(得分:4)

result_sm v = StateM (\s -> result_s (v, s))

对我来说错了。功能

\s -> result_s (v, s)

有类型

s -> State s (a,s)

StateM期望

s -> m (a,s)

适用于任意m,而不只是m ~ State s

你确定你不想要这样的东西:

result_sm :: (Monad m) => a -> StateM m s a
result_sm v = StateM (\s -> return (v, s))

(或应用变体)?