gpt4 book ai didi

typeclass - Purescript 行联合

转载 作者:行者123 更新时间:2023-12-04 15:55:19 25 4
gpt4 key购买 nike

我一直在尝试使用指定 eval 函数的 Component 类型类在 Purescript 中开发组件系统。 eval 函数可以由组件的每个子组件递归调用,实质上是获取输入的值。

由于组件可能希望使用运行时值,因此还向 eval 传递了一条记录。我的目标是要求顶级 eval 的 Record 参数中的行包含每个子组件的所有行。对于本身不使用任何行的组件来说,这并不是太困难,但它们的单个子组件确实如此,因为我们可以简单地将子组件行传递给组件。这显示在 evalIncrement 中.

import Prelude ((+), one)
import Data.Symbol (class IsSymbol, SProxy(..))
import Record (get)
import Prim.Row (class Cons, class Union)

class Component a b c | a -> b where
eval :: a -> Record c -> b

data Const a = Const a

instance evalConst :: Component (Const a) a r where
eval (Const v) r = v

data Var (a::Symbol) (b::Type) = Var

instance evalVar ::
( IsSymbol a
, Cons a b r' r) => Component (Var a b) b r where
eval _ r = get (SProxy :: SProxy a) r

data Inc a = Inc a

instance evalInc ::
( Component a Int r
) => Component (Inc a) Int r where
eval (Inc a) r = (eval a r) + one

以上所有代码都可以正常工作。但是,一旦我尝试引入一个接受多个输入组件并合并它们的行的组件,我似乎无法让它工作。例如,当尝试使用 class Union 时来自 Prim.Row :
data Add a b = Add a b

instance evalAdd ::
( Component a Int r1
, Component b Int r2
, Union r1 r2 r3
) => Component (Add a b) Int r3 where
eval (Add a b) r = (eval a r) + (eval b r)

产生以下错误:
  No type class instance was found for

Processor.Component a3
Int
r35


while applying a function eval
of type Component t0 t1 t2 => t0 -> { | t2 } -> t1
to argument a
while inferring the type of eval a
in value declaration evalAdd

where a3 is a rigid type variable
r35 is a rigid type variable
t0 is an unknown type
t1 is an unknown type
t2 is an unknown type

其实就算修改了 evalInc使用带有空行的虚拟联合的实例会产生类似的错误,如下所示:
instance evalInc :: (Component a Int r, Union r () r1) 
=> Component (Increment a) Int r1 where

我是否错误地使用了 Union?或者我是否需要为我的类(class)提供更多的功能依赖 - 我不太了解它们。

我正在使用 purs 版本 0.12.0

最佳答案

r ∷ r3但它被用于 r1r2是必需的,因此存在类型不匹配。一条记录 {a ∷ A, b ∷ B}不能在 {a ∷ A} 处给出或 {b ∷ B}{}是期待。然而,人们可以这样说:

f ∷ ∀ s r. Row.Cons "a" A s r ⇒ Record r → A
f {a} = a

换句话说, f是包含标签 "a" 的任何记录上的多态函数带类型 A .同样,您可以将 eval 更改为:
eval ∷ ∀ s r. Row.Union c s r ⇒ a → Record r → b

换句话说, eval在任何至少包含 c 字段的记录上是多态的.这引入了类型歧义,您必须使用代理来解决该歧义。
eval ∷ ∀ proxy s r. Row.Union c s r ⇒ proxy c → a → Record r → b

Add 的 eval 实例变为:
instance evalAdd ∷
( Component a Int r1
, Component b Int r2
, Union r1 s1 r3
, Union r2 s2 r3
) => Component (Add a b) Int r3 where
eval _ (Add a b) r = eval (RProxy ∷ RProxy r1) a r + eval (RProxy ∷ RProxy r2) b r

从这里开始, r1r2变得模棱两可,因为它们不是由 r3 确定的独自的。在给定的约束下, s1s2也必须知道。您可能会添加一个功能依赖项。我不确定什么是合适的,因为我不确定您正在设计的程序的目标是什么。

关于typeclass - Purescript 行联合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51422462/

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