0

В Haskell, мы знаем, что если мы имеем некоторую функцию f с сигнатурой типа f :: a -> a, то Haskell можно вывести следующие типы:трудно понять тип вывода в 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 s является экземпляром класса Monad, поэтому почему он не работает?

Кроме того, в отношении декларации экземпляра для Functor (StateM m s), я знаю, что компилятор не может вывести Monad m из контекста Functor m связанного с GHC-встроенный (натуральный/ип-переопределен) сигнатура типа для fmap.

Кроме того, в отношении объявления экземпляра для Applicative (StateM m s), я знаю, что компилятор также не может вывести Monad m из контекста (Functor (StateM m s), Applicative m) связанного типа подписей GHC-встроенный (натуральный/деинсталлировать переопределен) для pure и <*>.

Итак, мой второй вопрос заключается в следующем: как я могу заставить компилятор принять m в качестве экземпляра Monad typeclass в двух вышеупомянутых объявлениях экземпляра и любых подобных экземплярах?

{-# 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)' 
+0

Что такое ошибка компилятора вы получаете? – Bergi

+0

Теперь я буду добавлять полные сообщения об ошибках выше. – John

+1

"* Я бы хотел, чтобы переменная типа m была выведена *" - это не так, как она работает. Типы выводятся a) если они не даны b) проверять данные на правильность.Ошибка компилятора сообщает вам, что тип (непеременная) 'State s0', но вы указали ему переменную' m'. – Bergi

ответ

4

Компилятор выполнил свою работу. Ваш код не имеет смысла.

  1. В result_sm, вы пытаетесь построить StateM m s a с State 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, в том числе в Functor, Applicative и Monad экземпляров 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 .. 
    
+0

Хороший ответ, молодец. – John