首页 文章

难以理解Haskell中的类型推断

提问于
浏览
0

在Haskell中,我们知道如果我们有一些带有类型签名 f :: a -> a 的函数 f ,那么Haskell可以推断出以下类型:

f "alpha" 将具有 [Char] 类型;

f 1234 将具有 Num a => a 类型

f Just 的类型为 a -> Maybe a

等等 .

参考以下代码,

在函数 result_sm :: (Monad m) => a -> State m s a 中,我希望将类型变量 m 推断为 State s . State sMonad 类型类的实例,为什么它不起作用?

另外,关于 Functor (StateM m s) 的实例声明,我知道编译器不能从 fmap 的ghc -inbuilt(自然/未重写)类型签名绑定的上下文 Functor m 中推断 Monad m .

类似地,关于 Applicative (StateM m s) 的实例声明,我知道编译器也不能从 pure<*> 的ghc -inbuilt(自然/未重写)类型签名绑定的上下文 (Functor (StateM m s), Applicative m) 中推断出 Monad m .

所以我的第二个问题如下:如何让编译器接受 m 作为上述两个实例声明中的 Monad 类型类的实例,以及任何类似的实例声明?

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}

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 :: (Monad m) => a -> StateM m s a
result_sm v = StateM (\s -> result_s (v, s))

bind_sm :: (Monad m) => StateM m s a -> (a -> StateM m s b) -> StateM m s b
bind_sm stm f = StateM $ \s -> (tmp s >>= 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 m => Functor (StateM m s) where
  fmap :: (Monad m) => (a -> b) -> StateM m s a -> StateM m s b
  fmap f stm = stm `bind_sm` (result_sm . f)

instance Applicative m => Applicative (StateM m s) where
  pure :: (Monad m) => a -> StateM m s a
  pure = result_sm

  (<*>) :: (Monad m) => StateM m s (a -> b) -> StateM m s a -> StateM m s b
  p <*> q = p `bind_sm` \f ->
            q `bind_sm` (pure . f)

instance Monad m => Monad (StateM m s) where
  return = pure
  (>>=)  = bind_sm

这是完整的编译器错误消息 . 有人(用户名:Bergi)希望看到他们 .

StateParser.hs:29:29:
    Couldn't match type `m' with `State s0'
      `m' is a rigid type variable bound by
          the type signature for result_sm :: Monad m => a -> StateM m s a
          at StateParser.hs:28:14
    Expected type: m (a, s)
      Actual type: State s0 (a, s)
    Relevant bindings include
      result_sm :: a -> StateM m s a (bound at StateParser.hs:29:1)
    In the expression: result_s (v, s)
    In the first argument of `StateM', namely
      `(\ s -> result_s (v, s))'

StateParser.hs:52:11:
    Could not deduce (Monad m)
    from the context (Functor m)
      bound by the type signature for
                 fmap :: Functor m => (a -> b) -> StateM m s a -> StateM m s b
      at StateParser.hs:52:11-63
    Possible fix:
      add (Monad m) to the context of
        the type signature for
          fmap :: Functor m => (a -> b) -> StateM m s a -> StateM m s b
    When checking that:
        forall (m :: * -> *) s.
        Functor m =>
        forall a b. Monad m => (a -> b) -> StateM m s a -> StateM m s b
      is more polymorphic than:
        forall (m :: * -> *) s.
        Functor m =>
        forall a b. (a -> b) -> StateM m s a -> StateM m s b
    When checking that instance signature for `fmap'
      is more general than its signature in the class
      Instance sig: forall (m :: * -> *) s.
                    Functor m =>
                    forall a b. Monad m => (a -> b) -> StateM m s a -> StateM m s b
         Class sig: forall (m :: * -> *) s.
                    Functor m =>
                    forall a b. (a -> b) -> StateM m s a -> StateM m s b
    In the instance declaration for `Functor (StateM m s)'

StateParser.hs:56:11:
    Could not deduce (Monad m)
    from the context (Functor (StateM m s), Applicative m)
      bound by the type signature for
                 pure :: (Functor (StateM m s), Applicative m) => a -> StateM m s a
      at StateParser.hs:56:11-40
    Possible fix:
      add (Monad m) to the context of
        the type signature for
          pure :: (Functor (StateM m s), Applicative m) => a -> StateM m s a
    When checking that:
        forall (m :: * -> *) s.
        (Functor (StateM m s), Applicative m) =>
        forall a. Monad m => a -> StateM m s a
      is more polymorphic than:
        forall (m :: * -> *) s.
        (Functor (StateM m s), Applicative m) =>
        forall a. a -> StateM m s a
    When checking that instance signature for `pure'
      is more general than its signature in the class
      Instance sig: forall (m :: * -> *) s.
                    (Functor (StateM m s), Applicative m) =>
                    forall a. Monad m => a -> StateM m s a
         Class sig: forall (m :: * -> *) s.
                    (Functor (StateM m s), Applicative m) =>
                    forall a. a -> StateM m s a
    In the instance declaration for `Applicative (StateM m s)'

StateParser.hs:59:12:
    Could not deduce (Monad m)
    from the context (Functor (StateM m s), Applicative m)
      bound by the type signature for
                 (<*>) :: (Functor (StateM m s), Applicative m) =>
                          StateM m s (a -> b) -> StateM m s a -> StateM m s b
      at StateParser.hs:59:12-75
    Possible fix:
      add (Monad m) to the context of
        the type signature for
          (<*>) :: (Functor (StateM m s), Applicative m) =>
                   StateM m s (a -> b) -> StateM m s a -> StateM m s b
    When checking that:
        forall (m :: * -> *) s.
        (Functor (StateM m s), Applicative m) =>
        forall a b.
        Monad m =>
        StateM m s (a -> b) -> StateM m s a -> StateM m s b
      is more polymorphic than:
        forall (m :: * -> *) s.
        (Functor (StateM m s), Applicative m) =>
        forall a b. StateM m s (a -> b) -> StateM m s a -> StateM m s b
    When checking that instance signature for `<*>'
      is more general than its signature in the class
      Instance sig: forall (m :: * -> *) s.
                    (Functor (StateM m s), Applicative m) =>
                    forall a b.
                    Monad m =>
                    StateM m s (a -> b) -> StateM m s a -> StateM m s b
         Class sig: forall (m :: * -> *) s.
                    (Functor (StateM m s), Applicative m) =>
                    forall a b. StateM m s (a -> b) -> StateM m s a -> StateM m s b
    In the instance declaration for `Applicative (StateM m s)'

1 回答

  • 4

    编译器完成了它的工作 . 你的代码没有意义 .

    • result_sm 中,您正在尝试使用 State s a 构造 StateM m s a ,这是类型不匹配 . 你可能想做的是
    result_sm :: (Monad m) => a -> StateM m s a
    result_sm v = StateM (\s -> return (v, s))
    
    • 由于 bind_sm 上有约束 Monad m ,因此无论何时使用 bind_sm ,都需要携带该约束,包括 FunctorApplicativeMonad 实例 bind_sm . 因此,这些应该阅读
    instance Monad m => Functor (StateM m s) where ..
    instance Monad m => Applicative (StateM m s) where ..
    instance Monad m => Monad (StateM m s) where ..
    

相关问题