如何将 monadic 函数作为参数传递给灵活类型变量?
How can I pass a monadic function as an argument with a flexible type variable?
抱歉问题标题可能含糊不清 - 我不确定如何措辞,因为我对问题的理解很差。
基本上,我如何进行以下编译? :-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
但无济于事。
是否有我可以用来帮助编译器的扩展,或者从 type-inference 的角度来看,是否有一些概念上与我正在尝试做的事情不符?
你是对的,你需要 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)
抱歉问题标题可能含糊不清 - 我不确定如何措辞,因为我对问题的理解很差。
基本上,我如何进行以下编译? :-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
但无济于事。
是否有我可以用来帮助编译器的扩展,或者从 type-inference 的角度来看,是否有一些概念上与我正在尝试做的事情不符?
你是对的,你需要 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)