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