Типовые ограничения для полиморфных функций, таких как lift
Итак, у меня есть этот код
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import MonadA
data A = A
newtype MonadA a => MyStateT a b { runMyStateT :: StateT A a b }
deriving (Functor, Applicative, Monad, MonadIO, MonadState A)
instance MonadTrans MyStateT where
lift = MyStateT . lift
и я получаю компилятор, жалующийся, что он не может доказать m
от подписи lift
имеет тип MonadA
или вот как я читаю эти загадочные сообщения об ошибках.
Could not deduce (MonadA m) arising from a use of `MyStateT'
from the context (Monad m)
bound by the type signature for
lift :: Monad m => m a -> MyStateT m a
Есть ли способ справиться с этим? Я думаю, что мне нужно ограничение, чтобы иметь возможность создавать следующие экземпляры:
instance MonadA a => MonadA (MyStateT a) where
f = MyStateT . lift . f
Также была бы такая реализация f
Работа? (Я не получил это далеко из-за вышеуказанной ошибки). я надеюсь f
на правой стороне, чтобы решить f
по внутренней монаде a
,
Изменить: Это действительно помогло сбросить ограничение типа в newtype MonadA a => MyStateT ...
чтобы избежать точной ошибки, которую я упомянул. Однако произошла еще одна ошибка, которую я ранее приписал той же вещи, рассмотрим продолжение этого примера кода выше (некоторые части повторяются, теперь без ограничений типа):
class MonadB m where
fB :: m ()
newtype MyStateT m a = MyStateT { runMyStateT :: StateT A m a}
deriving (... MonadState A ...)
instance MonadTrans MyStateT where
lift = MyStateT . lift
instance MonadA a => MonadA (MyStateT a) where
f = lift . f
instance MonadA a => MonadB (MyStateT a) where
fB = lift (modify (...))
ошибка
Could not deduce (a ~ StateT A m0) from context (MonadA (MyStateT a), MonadA a)
в реализации fB
, Раньше пробовал class MonadA m => MonadB m
но безрезультатно. Даже не имеет смысла соответствовать a
с StateT A m
, поскольку MyStateT
это пример MonadState A
это должно работать, нет?
Редактировать:
ОК, все заработало:
fB = MyStateT (modify ...)
глупый я.
1 ответ
Решение сбрасывает ограничение с MyStateT
определение:
newtype MyStateT a b { runMyStateT :: StateT A a b }
deriving (Functor, Applicative, Monad, MonadIO, MonadState A)
Ограничения типов данных по сути бесполезны, так как в любом случае их необходимо помещать в сигнатуры функций. По этой причине эта функция фактически устарела.
Я думаю, что мне нужно ограничение, чтобы иметь возможность создавать следующие экземпляры:
На самом деле, нет; instance MonadA a => MonadA (MyStateT a)
без него будет нормально работать.
Также была бы такая реализация
f
Работа?
Будет. Обратите внимание, что, как вы предоставили MonadTrans
экземпляр для MyStateT
вам на самом деле не нужно оборачиваться MyStateT
в явном виде:
instance MonadA a => MonadA (MyStateT a) where
f = lift . f