haskell - 类型类函数的显式 forall
问题描述
从 ghc-8.0 开始,我们有一个非常好的扩展名为TypeApplications
. 这允许我们而不是:
λ> show (5 :: Int)
"5"
这样做:
λ> :set -XTypeApplications
λ> show @Int 5
"5"
这真的很酷。当我们添加更多类型变量时,它会变得更加复杂,但是有一些规则可以用来确定确切的顺序,并且它们有很好的文档记录:
showFooBar :: (Show a, Show b) => a -> b -> String
showFooBar a b = show a ++ " and " ++ show b
所以在上面的函数中,我们首先提供a
然后b
:
λ> showFooBar @Int @Double 3 4
"3 and 4.0"
很好,但是如果我想更改顺序怎么办?没问题,我们可以使用ExplicitForAll
扩展(或其他暗示它)来指定它:
{-# LANGUAGE ExplicitForAll #-}
showFooBar :: forall b a . (Show a, Show b) => a -> b -> String
showFooBar a b = show a ++ " and " ++ show b
现在我们颠倒了我们要应用的类型的顺序:
λ> showFooBar @Int @Double 3 4
"3.0 and 4"
问题是我似乎无法弄清楚如何对属于类型类的函数实现相同的影响。考虑这个例子:
{-# LANGUAGE MultiParamTypeClasses #-}
class (Show a, Show b) => FooBar a b where
fooBarClassFunc :: a -> b -> String
我现在不能forall
使用函数(例如fooBarClassFunc :: forall a b . a -> b -> ..
,因为这会改变函数的含义并且显然无法编译。
所以,问题是,如何TypeApplication
在类型类方法内部更改类型变量的顺序?
编辑
以防万一,我尝试InstanceSigs
了扩展,它完全忽略了forall
类型变量的顺序TypeApplications
,这是一件好事,否则我们最终会得到由实例而不是类决定的行为。
解决方案
TypeApplication
为了类型类方法内部的目的,您如何更改类型变量的顺序?
我认为@luqui 的回答已经足够好了。但为什么不这样:
class (Show b, Show a) => FooBar b a where
fooBarClassFunc :: a -> b -> String
您只有一个方法,因此将参数顺序驱动到类的唯一考虑是为了TypeApplication
在方法内部。
如果您有两个或多个方法希望顺序TypeApplication
不同(@chi 的观点,但为什么?),那么对于其他方法,或者是 luqui 的建议,或者(等效地)具有超类约束和默认值的其他类执行。
class (Show a, Show b, FooBar b a) => OtherFooBar a b where
otherFooBarClassFunc :: a -> b -> String
otherFooBarClassFunc = otherFooBarClassFunc' -- default
instance {-# NOOVERLAPPABLE #-} OtherFooBar a b where {} -- take default
(假设otherFooBarClassFunc'
在主类中定义;这就是真正的实例定义的地方。)
当然,对于每个类的一种方法,有很多话要说。
{-# NOOVERLAPPABLE #-}
我们不知道的是我的小笑话。
推荐阅读
- ms-access-2016 - 错误您尝试打开的数据库需要更新版本的 Microsoft Access
- java - Spring boot如何实现Error页面
- gremlin - 如何排除不包含值的顶点
- c++ - 如何为给定的测试用例解决这个 geeksforgeeks 问题?
- javascript - Highchart 根据 y 轴的值改变十字准线颜色
- algorithm - 以下程序的时间复杂度是多少?
- output - 问题:带有附加 1 的 plm 包虚拟变量的输出
- azure - 如何获取 azure 管道的最后运行 id?
- imagemagick - 识别命令输出中的颜色图和直方图有什么区别?
- nginx - www 在域中返回超时,在我在 nginx 中使用正则表达式添加重定向之后