generics - Haskell 中的泛型类型转换

标签 generics haskell types arrows algebraic-data-types

我正在尝试写一个 arrow使用常规函数并将它们转换为对抽象值的计算的转换器。如果我们有一个“源”箭头,

f :: Int -> Int
f x = x + 1

那么目标是让 f 处理提升的 [原文如此?] 抽象值类型,在这个例子中
f' :: AV Int -> AV Int
f' (Const x) = Const (f x)
-- pass along errors, since AV computation isn't always defined
-- or computable in the case of errors
f' (Error s) = Error s
-- avRep = "abstract representation". Think of symbolic math manipulation or ASTs.
f' (Abstract avRep) = AVRepPlus avRep (AVRepConst 1)

然而,为了成功地实现这个箭头,一个人需要解除几个类型,这样一个人就有具有一些具体值和一些抽象值的异构数据结构 ,在任意深度。我最终做的是为常规的 Haskell 构造函数添加特殊类型,例如如果
g = uncurry (+) -- i.e. g (x, y) = x + y

然后我为 (,) 添加一个抽象表示,元组构造函数,
AVTuple :: AV a -> AV b -> AV (a, b)

将 g 的代码提升为 [展开一点],
g' (AVTuple (AVConst a) (AVConst b)) = (AVConst (g (a, b)))
g' (AVTuple (AVError e) _) = (AVError e)
-- symmetric case here, i.e. AVTuple _ (AVError e)
g' (AVTuple a@(AVTuple _ _) b) = -- recursive code here

AVEither 也需要这样做。这将最终成为很多案例。有没有好的办法解决这个问题?

我是 Haskell 新手,所以请给我发送引用资料或半详细说明;可能我读过的最接近的东西是 SYBR 论文(废弃你的样板革命)第 1-3 节。

非常非常感谢你!

最佳答案

让我看看我是否明白你在这里的目的。你有一个类型 AV a它描述了产生 a 类型的东西的计算,其中可以以允许检查的方式保留该计算的结构。您想要一种将任意函数提升到 AV 上的操作的方法。 ,保留结构,而不必为每个操作创建特殊情况。

通常,为了将函数提升到某种结构中,可以使用 FunctorApplicative .但是,这样做的直接方法涉及转换结构并直接应用提升的函数,而不是将函数应用程序保留为结构的一部分。

你想要的更尴尬,这就是原因:

假设我们有一些我们想要提升的函数,以及两个适当类型的抽象值来应用它:

x :: AV A
x = ...

y :: AV B
y = ...

f :: A -> B -> C
f = ...

假设存在一个函数 liftAV2这就是你想要的。我们预计 lift2 f 的类型成为 AV A -> AV B -> AV C ,就像 liftAApplicative .

稍后,我们要检查使用 lift2 f 产生的计算。 ,通过恢复 f 的值, x , 和 y .假设现在我们只想提取第一个参数。假设存在一个函数 extractArg1这样做,使得 extractArg1 (liftAV2 f x y) = x . extractArg1的类型是什么?在这里,在上下文中,我们知道它应该具有类型 AV C -> AV A .但它一般有什么类型?类似 AV c -> AV a ?这是错误的,因为结果不只是任何类型 a ,它是用于构造 AV c 的任何类型值(value)。假设我们正在操作的值是使用 liftAV2 f 的结果构建的,我们知道有问题的类型存在,但我们没有办法找到它。

这是我们进入土地的地方,足够恰当,存在类型 .诚实地使用它们,不少于,而不是像通常那样将它们与类型类一起使用。

您可能可以通过一些努力来完成您所追求的目标,但这已经进入了相当先进的领域。你会想要使用 GADT 对于初学者来说,虽然我认为你可能已经这样做了。使用存在类型也往往非常笨拙,因为您只能在有限的上下文中知道它们是什么。

在您的具体情况下,提供 AV 可能更容易两种类型参数:一种表示计算的最终类型,一种表示计算的结构,例如:
data f :$ x = ...

data AV structure result where
    ...
    AVApply :: AV f (a -> b) -> AV x a -> AV (f :$ x) b

然后,为了检查计算,您可以查看第一种类型以了解您拥有什么;为了构建计算,您可以查看第二个以确保类型匹配。评估函数的类型类似于 AV t a -> a ,扔掉结构。如果您需要拆开结构以便漂亮地打印它,您还可以使用结构类型“解包”计算,丢弃结果类型。

关于generics - Haskell 中的泛型类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5840610/

相关文章:

function - 在 haskell 中检查函数参数的最佳方法

c# - 带有泛型的 Unity3D GetComponent

c# - 在 C# 中使用泛型和接口(interface)时如何避免强制转换

haskell - 如果文件的一部分发生更改则运行操作

haskell - 从列表中删除所有实例

types - BISON/FLEX C-Basic没有声明类型错误

javascript - 具有键值 NaN 属性的异常数组,包含更多数组?

android - HTML5 - Android 平板电脑 - 输入类型编号

java - 泛型和 Class.forName

c# - 如何使用约束将 T 限制为值类型?