haskell - 在类型类函数上显式 forall

标签 haskell typeclass 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 扩展,就 TypeApplications 而言,它完全忽略了 forall 类型变量的顺序,这是一件好事,否则我们最终会得到由实例而不是类决定的行为。

最佳答案

how do you change the order of type variables for the purpose of TypeApplication inside the type class methods?

我认为@luqui 的回答已经足够好了。但为什么不这样呢:

class (Show b, Show a) => FooBar b a where
  fooBarClassFunc :: a -> b -> String

您只有一个方法,因此驱动类参数顺序的唯一考虑因素是为了方法内的 TypeApplication 的目的。

如果您有两个或多个方法,您希望 TypeApplication 的顺序不同(@chi 的观点,但为什么?),那么对于其他方法,要么 luqui 的建议,要么(等效地) ) 具有父类(super class)约束和默认实现的另一个类。

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' 在主类中定义;这就是实际实例定义的地方。)

one method per class 有很多话要说。 ,当然。

{-# NOOVERLAPPABLE #-} 我们不知道这是我的小笑话。

关于haskell - 在类型类函数上显式 forall,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54700136/

相关文章:

mysql - HAVING 查询的问题

haskell - "exists"在 Haskell 类型系统中意味着什么?

haskell - Applicative/Monad 实例对于 Sum 和 Product 有什么用?

haskell - 为什么我对 signum 的定义类型正确?

python - 使用单行生成列表直到满足特定条件

scala - 尝试实现 `Absurd` 类型类时的隐式错误

haskell - Haskell 中的类型签名中的 `... -> t a ->...` 是什么意思?

scala - 关于类型类的问题

haskell - GHC 如何使用 Num 实例将多态数字文字转换为任意类型?