[英]Why can't a function take a type constrained only by a typeclass?
我没有足够的词汇来表达这个问题(因此,为了寻找答案,如果答案很容易获得,那么道歉)。 考虑以下
class RunFoo m where
runFoo :: m a -> a
class RunFooWrapper m where
doRunFoo :: (RunFoo n) => n a -> m a
newtype RunFast a = RunFast a
newtype RunSlow a = RunSlow a
fooExample :: (RunFoo m) => m Bool
fooExample = undefined
fooWrapperExample :: (RunFooWrapper m) => m Bool
fooWrapperExample = doRunFoo fooExample
这不编译: Could not deduce (RunFoo n0) arising from a use of 'doRunFoo'
。
似乎编译器(GHC 7.10)坚持从fooExample
具体实例化m
,因此拒绝继续。 但在这种情况下,我无法fooExample
为什么程序是错误类型的 - fooExample
显式定义了RunFoo m
,所有doRunFoo
需要的是RunFoo x
。 那么为什么这不起作用呢?
作为一个补充问题,是否存在某种特殊的扩展(可能与存在类型有关),允许这样的程序? 理想情况下,我希望能够说doRunFoo采用存在的任何定义(?)作为RunFoo m => m
(而不是采用任何具体的RunFoo
实例)。
动机
我想创建可组合函数,这些函数在类型类约束的类型的某些方面运行 - 我可以提供一个具体的例子,说明我的意思,如果有必要的话!
编辑更多的动力和替代实施
我对一般情况下这个问题的答案感到好奇,但我想我会在上下文中添加一些我遇到的问题,我真正想要的是monad之间的一种约束委托。 所以我想在一个monad中编写函数,只能通过在另一个类型类中调用monad的类型类来约束。 然后可以在不同的上下文中运行顶级函数,执行相同的逻辑,但根据包装monad将底层实现换出。 由于包装和实现monad之间存在一对一的对应关系,我可以使用类型系列来实现这一点,所以
class (RunFoo (RunFooM m)) => RunFooWrapper m where
type RunFooM m :: * -> *
doRunFoo :: RunFooM m a -> m a
instance RunFooWrapper RunFooWrapperSlow where
type RunFooM RunFooWrapperSlow = RunSlow
doRunFoo :: [...]
这意味着fooExample
m
的分辨率由包装器monad的类上下文决定,并且似乎工作正常,但与haoformayor提供的解决方案相比,它是一个非常狭窄的解决方案。
{-# language RankNTypes #-}
class RunFoo m where
runFoo :: m a -> a
class RunFooWrapper m where
doRunFoo :: (forall n. RunFoo n => n a) -> m a
fooExample :: RunFoo m => m Bool
fooExample = undefined
fooWrapperExample :: RunFooWrapper m => m Bool
fooWrapperExample = doRunFoo fooExample
(forall n. RunFoo n => na) -> ma
是关键区别。 它允许您传入fooExample
,其类型为forall m. RunFoo m => m Bool
forall m. RunFoo m => m Bool
(编译器隐式添加了forall
),因此m
与n
结合,每个人都很高兴。 虽然我无法读懂思想,但我相信这种类型反映了你的真实意图。 您只需要一个RunFoo
实例,仅此而已将n
作用于第一个参数提供它。
问题是你的代码被隐式输入为forall n. RunFoo n => na -> ma
forall n. RunFoo n => na -> ma
。 这意味着你需要首先选择一个n
,使得RunFoo n
然后提出一个类型为na
的值作为第一个参数传入。 移动括号的这种简单行为(增加n
的等级)完全改变了含义。
有关具有相同问题的人的示例,请参阅此Stack Overflow问题 。 有关RankNTypes
的更好解释,请参阅Oliver的博客文章 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.