派生读入 Haskell:为什么我必须使用构造函数的参数名称?

Deriving Read in Haskell: Why do I have to use the contructor's parameter names?

我一直在试验 deriving 并且很难理解 deriving (Read) 的工作原理。

我们来看看下面的数据定义:

data Data         = D Int deriving (Eq, Read, Show)
data DataWithName = DWN { val :: Int } deriving (Eq, Read, Show)

没什么特别的,只是两种数据类型,每种都封装了一个 Int,但第二种数据类型为 Int.

引入了名称 val

在交互式控制台中,以下说明按预期工作:

*Main> D 5
D 5
*Main> DWN 5
DWN {val = 5}
*Main> DWN { val = 5 }
DWN {val = 5}

虽然以下一个不起作用(编辑:我预计这不起作用)

*Main> D { val = 5 }

<interactive>:11:1:
    Constructor `D' does not have field `val'
    In the expression: D {val = 5}
    In an equation for `it': it = D {val = 5}

现在让我们归结为:

我认为派生 Read 会给我相同的方法来输入数据类型,但在下面的第 1 行和第 2 行中有效,而第 3 行无效,因为参数名称不是给定:

d1 = read "D 1" :: Data -- Works
d2 = read "DWN { value = 1 }" :: DataWithName -- Works
d3 = read "DWN 1" :: DataWithName -- This does not work because parameter is not given.

是否有可能使 derving (Read) 也派生出 "non-parameter-name constructor",这样 read "DWN 5" :: DataWithName 就可以与 "parameter-name constructor" 一起工作?

或者您能否提供一些有关如何处理数据读取/输入的信息?

谢谢!

I thought that deriving Read would give me the same ways how to enter a data type, but in the following line 1 and line 2 work, while line 3 does not work ...

这不是 Read 所做的或 deriving 实现的。事实上,表达式 D { val = 5 } 根本不正确。 val 只是您从记录构造中得到的另一个正常函数。你甚至可以检查它的类型:

ghci| > :t val
val :: DataWithName -> Int

数据构造函数 D 只接受 Int 作为参数,其类型证明了这一点:

ghci| > :t D
D :: Int -> Data

所以无论你做什么,你都不能给它类似 D { val = 5 } 的东西,因为它是一个类型错误。

Is there some possibility to enable deriving (Read) to also derive the "non-parameter-name constructor" such that read "DWN 5" :: DataWithName would work additionally to the "parameter-name constructor"?

没有。但是您可以对 String 进行一些解析并手动将其转换为所需的数据结构。