难以理解Haskell中的类型推断

时间:2016-08-28 22:15:05

标签: haskell types functional-programming monads template-haskell

在Haskell中,我们知道如果我们有一些带有类型签名f的函数f :: a -> a,那么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(自然/未覆盖)类型绑定的上下文Monad m推导出Functor m fmap的签名。

同样,关于Applicative (StateM m s)的实例声明,我知道编译器也不能从ghc -inbuilt(自然/未覆盖)绑定的上下文Monad m推导出(Functor (StateM m s), Applicative m)类型为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 个答案:

答案 0 :(得分:4)

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

  1. Image中,您尝试使用OnPointerUp构建Cache-Control: public, max-age=0,这是类型不匹配。你可能想要做的是

    result_sm
  2. 由于StateM m s a上有State s a约束,因此您需要在result_sm :: (Monad m) => a -> StateM m s a result_sm v = StateM (\s -> return (v, s)) 的任何位置使用该约束,包括bind_sm,{{1} {}}和Monad m bind_smFunctor个实例。因此,这些应该阅读

    Applicative