Рассмотрим следующий код:
data MyBaseExpr α where
ConstE :: Show α => α -> MyBaseExpr α
class Monad ? => MyMonadCls ? where
type ExprTyp ? :: * -> *
var :: String -> ExprTyp ? α -> ? (ExprTyp ? α)
expTypArg :: forall ? α. MyMonadCls ? => ExprTyp ? α -> ? α
expTypArg a = undefined
-- dummy type which will be used as an instance
newtype A ? α = A (? α)
Затем, если кто-то пытается написать экземпляр, используя функцию expTypeArg,
instance forall ?. (Monad ?, Monad (A ?)) => MyMonadCls (A ?) where
type ExprTyp (A ?) = MyBaseExpr
var nme init@(expTypArg -> typb) =
return init
компилятор жалуется
Couldn't match type `ExprTyp ?0' with `MyBaseExpr'
Expected type: ExprTyp (A ?) α
Actual type: ExprTyp ?0 α
Но, если добавить несколько выражений типа scoped,
instance forall ?. (Monad ?, Monad (A ?)) => MyMonadCls (A ?) where
type ExprTyp (A ?) = MyBaseExpr
var nme init@((expTypArg :: MyMonadCls (A ?) =>
ExprTyp (A ?) α ->
(A ? α)) -> typb) =
return init
, то это разрешится нормально.Что за проблема решается ExprTyp == MyBaseExpr
для expTypArg
?
edit
Большое спасибо, Даниэль!Вот способ убрать некоторые из пустяков, заметив, что нужно применять только тип ?
.
ignore_comp :: ? α -> ? β -> ? β
ignore_comp a b = b
instance forall ?. (Monad ?, Monad (A ?)) => MyMonadCls (A ?) where
type ExprTyp (A ?) = MyBaseExpr
var nme init@(expTypArg -> typb) =
typb `ignore_comp`
return init