gpt4 book ai didi

haskell - 类型类 TF 的实例声明非法

转载 作者:行者123 更新时间:2023-12-02 14:48:35 26 4
gpt4 key购买 nike

我在声明以下类型类的实例时遇到问题。我尝试遵循 ghci 编译器错误消息中的建议,但仍然无法编译代码。任何帮助将不胜感激。

class TF p where 
valid :: p -> Bool
lequiv :: p -> p -> Bool

instance TF Bool
where
valid = id
lequiv f g = f == g

instance TF p => TF (Bool -> p)
where
valid f = valid (f True) && valid (f False)
lequiv f g = (f True) `lequiv` (g True)
&& (f False) `lequiv` (g False)

我收到的错误是:

Illegal instance declaration for ‘TF (Bool -> p)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for ‘TF (Bool -> p)’

最佳答案

这里的问题是您有一个类型构造函数( -> )应用于非类型变量的事物。有很多方法可以解决这个问题:

  1. FlexibleInstances 。这放松了假设(在 Haskell 早期做出的,当时还不清楚实现类型类有多困难)。这根本不是很有争议。另一方面,它在类型推断方面表现不佳:只有当我们知道我们提供的形状为 Bool -> p 时,才会选择您的实例。 ——特别是第一个参数中的多态性将与该形状不匹配。所以valid id如果没有进一步的注释,将不会进行类型检查。
  2. TypeFamilies 。这使我们(除其他外)可以访问要求两个特定类型相等的约束。因此,使用此扩展,您可以编写

    instance (bool ~ Bool, TF p) => TF (bool -> p) where ...

    现在只要我们提供的东西有形状 bool -> p 就会匹配-- 也就是说,任何函数 -- 并且只有在我们选择此实例之后,它才会检查(实际上是强制执行)参数类型是否为 Bool 。这意味着valid id将进行类型检查;另一方面,这也意味着您无法声明任何其他参数类型的实例。

  3. 添加类型类。事实上,您唯一真正关心的是您可以列出 Bool 的所有居民。在没有太多时间的情况下。因此,您可以声明一个类型类,例如 Finite ,您将在此类类型上实例化它,并使用它作为参数类型的约束。因此:

    instance (Finite arg, TF p) => TF (arg -> p) where
    valid f = all (valid . f) universe
    lequiv f g = all (\x -> f x `lequiv` g x) universe
    -- could also spell that lambda "liftA2 lequiv f g"

    然后您需要提供 Finite Bool 的实例(幸运的是,您已经可以在 universe 包中找到它)。这很好,因为它结合了前两种方法的优点:一旦我们知道参数是函数,就会选择该实例,并且您可以通过添加 Finite 来声明许多参数类型的实例。他们的实例。

关于haskell - 类型类 TF 的实例声明非法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23910988/

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