【问题标题】:Why am I getting a type mismatch error?为什么我会收到类型不匹配错误?
【发布时间】: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 sStateM f s 非常明确地定义了Functor 类型类的实例,这应该允许它们与类型变量m 匹配,由Functor 类型类绑定在bind_smresult_sm

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

【问题讨论】:

  • 这里没有魔法发生——你的函数完全是错误的(类型不正确),类型检查器完全正确地拒绝它。由于编译器已经准确地告诉你程序为什么不正确,你是否尝试过修复它告诉你错误的东西? (你读过错误吗?)至少,StateM $ \s -&gt; .. `bind_sm` .. 意味着StateM 应该有类型s -&gt; StateM m0 x0 (StateM m1 x1 (a,s)),它显然没有。

标签: haskell types functional-programming type-conversion


【解决方案1】:
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))

(或应用变体)?

【讨论】:

  • 是与上面的代码有关的错误,还是与用户有关的错误。后者是可以理解的,因为必须更改类型签名。
  • @UnchartedWaters,您对自己的事业没有多大帮助。 @chi 显示的代码确实解决了result_sm 的问题,如下所示:lpaste.net/180892 您在bind_sm 和其他方面还有其他问题,但这是对您的第一个错误的修复。
猜你喜欢
  • 2022-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-27
  • 2013-04-22
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
相关资源
最近更新 更多