gpt4 book ai didi

haskell - 类型类及其实例之间的 ScopedTypeVariables

转载 作者:行者123 更新时间:2023-12-02 01:44:37 26 4
gpt4 key购买 nike

Haskell wiki on ScopedTypeVariables没有描述如何在类型类及其实例之间处理类型变量的范围。

编译如下

{-# LANGUAGE ScopedTypeVariables #-}
class A a where
f :: forall b. a -> b -> (a,b)

instance A Int where
f a b = (idb a, ida b)
where idb :: b -> b
idb = id
ida :: a -> a
ida = id

而以下不是(如预期的那样:Couldn't match expected type ‘a’ with actual type ‘b’)

g :: forall a b. a -> b -> (a,b)
g a b = (idb a, b)
where idb :: b -> b
idb = id

既然 wiki 是沉默的,那么 ScopedTypeVariables 应该如何与类型类一起工作?这是错误、功能不全还是设计使然? wiki 提到了一些 Haskell98 的变通办法,它们似乎与使用类型类兼容(因此更优越)。

编辑:

如评论中所述,InstanceSigs 可以重新引入类的签名,从而将类型变量带入作用域。但与 Haskell98 替代方案相比,这似乎很尴尬:

data D
instance A D where
f a b = (idb a, b)
where idb x = asTypeOf b x -- gives the correct error message

{-# LANGUAGE InstanceSigs #-}
data E
instance A E where
-- Complicated way to bring the class signature into scope..?
f :: forall b. E -> b -> (E, b)
f a b = (idb a, b)
where idb :: b -> b
idb = id

在实例声明中重新使用类声明中的作用域以使 ScopedTypeVariables 与类型类很好地协同工作不是更有意义吗?

最佳答案

在实例定义中,您没有使用作用域类型变量。您只需在 where block 中为 idbida 提供注释,并且两者都被概括为相同的类型,即 forall a . a -> a (类型变量的模重命名),因此它们都适用于任何类型。

另外,在实例定义中你有 A Int,所以没有任何你可以引用的变量。

通常,如果我们有 ScopedTypeVariables,实例头中的类型变量在实例实现中默认可见,否则不可见。另外,请注意,当它们可见时,它们可能会被其他作用域类型变量遮蔽(就像任何其他作用域类型变量一样)。

例子:

class A a where
f :: a -> b -> (a,b)

instance A a where
f x y = (x :: a, y) -- an error without ScopedTypeVariables, fine with it.

instance A a where
f x y = (x , y) where
foo :: forall a. a -> a
foo _ = x -- an error, because we shadowed the instance "a" with the forall "a"

关于haskell - 类型类及其实例之间的 ScopedTypeVariables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26437134/

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