对其他实例使用命名实例

Use named instances for other instances

我正在尝试在 我的自定义 Bool 数据类型 上创建 SemigroupVerifiedSemigroup 实例,两者都在运算符 [=16= 上] 和运算符 ||:

%case data Lógico = Cierto | Falso

(&&) : Lógico -> Lógico -> Lógico
(&&) Cierto Cierto = Cierto
(&&) _ _ = Falso

(||) : Lógico -> Lógico -> Lógico
(||) Falso Falso = Falso
(||) _ _ = Cierto

所以我首先在 && 运算符上为 Semigroup 创建一个 命名实例

-- Todos
instance [TodosSemigroup] Semigroup Lógico where
    (<+>) a b = a && b

但是在创建 VerifiedSemigroup 实例时,如何告诉 Idris 使用 LógicoTodosSemigroup 实例?

instance [TodosVerifiedSemigroup] VerifiedSemigroup Lógico where
    semigroupOpIsAssociative l c r = ?vsemigroupTodos

该代码给我以下错误:

When elaborating type of Prelude.Algebra.Main.TodosVerifiedSemigroup, method semigroupOpIsAssociative: Can't resolve type class Semigroup Lógico

idris-dev 存储库中有一个 open issue。 Edwin Brady 表示

Currently (by design) named instances can only be used to resolve a class by being named explicitly, even if there is no normal instance.

所以这里我们让 Idris 尝试解析未命名的 Semigroup Lógico 实例,这是定义 VerifiedSemigroup Lógico 实例所必需的。

我们需要一些方法来在实例声明中指定命名实例应该用于满足 class 约束。我不知道这是否可能。从链接的问题中引用埃德温:

this behaviour isn't documented anywhere

using 关键字为此引入了新机制:

%case data Lógico = Cierto | Falso

(&&) : Lógico -> Lógico -> Lógico
(&&) Cierto Cierto = Cierto
(&&) _ _ = Falso

(||) : Lógico -> Lógico -> Lógico
(||) Falso Falso = Falso
(||) _ _ = Cierto

instance [TodosSemigroup] Semigroup Lógico where
    (<+>) a b = a && b

instance [TodosVerifiedSemigroup] VerifiedSemigroup Lógico using TodosSemigroup where
    semigroupOpIsAssociative l c r = ?vsemigroupTodos