Типовые ограничения для полиморфных функций, таких как 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
Другие вопросы по тегам