gpt4 book ai didi

haskell - 编译器不会为多态常量值选择类型类

转载 作者:行者123 更新时间:2023-12-02 14:51:43 24 4
gpt4 key购买 nike

我是 Haskell 的新手,请多多包涵。

为什么下面的 haskell 代码不能编译?

似乎编译器不知何故无法看到表达式 (maxBound::a) 的类型是 a ,它有一个 Enum 提供的实例,而不是一些类型变量“a0”,它不明确

class (Enum a, Bounded a) => SafeEnum a where
ssucc :: a -> a
ssucc x = if (fromEnum x) < (fromEnum (maxBound :: a)) then succ x else minBound

spred :: a -> a
spred x = if (fromEnum x) > (fromEnum (minBound :: a)) then pred x else maxBound
Stepik.hs:3:32: error:
• Could not deduce (Enum a0) arising from a use of ‘fromEnum’
from the context: SafeEnum a
bound by the class declaration for ‘SafeEnum’
at Stepik.hs:(1,1)-(6,82)
The type variable ‘a0’ is ambiguous
These potential instances exist:
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
...plus six others

最佳答案

默认情况下,即使类型变量的范围从被定义的类到类方法的类型签名(即 class SafeEnum a 中的 aassucc::a -> a 中的 a 相同),它们属于类型方法签名到方法体,因此在函数体 ssuccspred 的表达式 maxBound::a 中,a 与这些函数的类型签名中的 a 无关。

您可以启用 ScopedTypeVariables 扩展,如下所示:

{-# LANGUAGE ScopedTypeVariables #-}

之后类定义将进行类型检查。

请注意,如果您使用 forall 关键字,此扩展仅适用于“普通”函数声明。因此,在类定义之外,您需要启用此扩展写入:

ssucc :: forall a. a -> a 
ssucc x = ... maxBound :: a ...

或者实际上:

ssucc :: forall a. (Enum a, Bounded a) => a -> a
ssucc x = ... maxBound :: a ...

但是 class 子句中的规则是不同的。

参见 the GHC docs了解详情。

关于haskell - 编译器不会为多态常量值选择类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55230741/

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