难以理解 Haskell 中的类型推断

Having difficulty understanding type inference in Haskell

在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 sState sMonad 类型类的一个实例,为什么它不起作用?

此外,关于 Functor (StateM m s) 的实例声明,我知道编译器无法从 ghc-inbuilt (natural/un-overridden 绑定的上下文 Functor m 中推断出 Monad m ) fmap.

的类型签名

同样,关于 Applicative (StateM m s) 的实例声明,我知道编译器也无法从 ghc-inbuilt (natural/un-overridden) pure<*>.

的类型签名

所以我的第二个问题如下:如何让编译器在上述两个实例声明和任何类似的实例声明中接受 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. 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)) 
    
  2. 由于 bind_sm 上有约束 Monad m,因此无论在何处使用 bind_sm,都需要携带该约束,包括 FunctorApplicativebind_smMonad 个实例。因此,这些应该是

    instance Monad m => Functor (StateM m s) where ..
    instance Monad m => Applicative (StateM m s) where ..
    instance Monad m => Monad (StateM m s) where ..