gpt4 book ai didi

haskell - 为什么函数不能采用仅受类型类约束的类型?

转载 作者:行者123 更新时间:2023-12-04 22:43:09 24 4
gpt4 key购买 nike

我没有足够的词汇来表达这个问题(因此无法搜索答案,如果答案很容易获得,我深表歉意)。考虑以下

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)坚持要对 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 提供的解决方案相比,它是一个非常狭窄的解决方案。

最佳答案

RankNTypes

{-# 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 => n a) -> m a是关键的区别。它让你传入 fooExample ,其类型为 forall m. RunFoo m => m Bool (编译器隐式添加了 forall)等 mn 统一每个人都很开心。虽然我不能读心,但我相信这种类型反射(reflect)了你的真实意图。你只想要一个 RunFoo例如,仅此而已,还有 n作用域为第一个参数提供了它。

问题是您给定的代码被隐式输入为 forall n. RunFoo n => n a -> m a .这意味着您需要先选择一个 n使得 RunFoo n然后想出一个类型为 n a 的值作为第一个参数传入。这种移动括号的简单行为(增加 n 的等级)完全改变了含义。

有关遇到相同问题的人的示例,请参阅 this Stack Overflow question .为了更好地解释 RankNTypes我无法提供,请参阅 Oliver's blog post on it .

关于haskell - 为什么函数不能采用仅受类型类约束的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39478919/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com