为潜在的模糊问题标题道歉 - 我不确定如何表达它,因为我对问题的理解很差。
基本上,我如何进行以下编译? :-P
{-# LANGUAGE MultiParamTypeClasses #-}
class (Monad m) => MyClass m a where
valM :: m (Maybe a)
val :: m a
f :: (MyClass m a) => (m a -> IO a) -> IO (a, Maybe a)
f g = do
x <- g val
yM <- g valM
return (x, yM)
GHC(v8.2.2)抱怨a
是一个刚性类型变量,似乎无法应对(g val)
和(g valM)
可以产生不同类型值的观点。我尝试过使用RankNTypes
,但无济于事。
是否有一个我可以用来帮助编译器的扩展,或者从类型推断的角度来看,我正在尝试做什么概念?
你是对的,你需要RankNTypes
,但你错过了forall
。 f
的正确类型是:
f :: MyClass m a => (forall b. m b -> IO b) -> IO (a, Maybe a)
...因为传递给f
的函数必须适用于任何结果类型,并且它不应与结果中的a
相关。
值得注意的是,这种函数也称为自然变换,自然变换包为这些函数提供a (~>)
type alias:
type (~>) f g = forall a. f a -> g a
因此,使用该类型别名,您也可以像这样编写f
:
f :: MyClass m a => (m ~> IO) -> IO (a, Maybe a)