如何在记录中设置默认值

dop*_*man 10 haskell record

我正在尝试在可以覆盖的记录对象中设置默认值.

data Car c y = Car {
    company :: c,
    year :: y
    }
Run Code Online (Sandbox Code Playgroud)

我想做的是设置默认值:

data Car c y = Car {
    company :: c -- OR "Ford"
    year :: y
    }
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经尝试通过将c的Maybe类型设置为类型来执行此操作:

data Car = Car {
    company:: Maybe String
    year :: Maybe Int
    }
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个可预测的错误:

Fields of `Car' not initialised: year
Run Code Online (Sandbox Code Playgroud)

具有讽刺意味的是,这正是我想要解决的问题.我想生成一个新记录,其中包含我未设置的值已经初始化.我发现的一种方法是部分应用Car类型:

data Car c y = {
    company :: c,
    year :: y
    }

let ford = Car "Ford" 

-- This produces a function (y -> Car [Char] y)
Run Code Online (Sandbox Code Playgroud)

然而,这会产生两个新问题:

  1. 如果我的数据类型有100多个字段类型,我最终会得到100个因子curry函数

  2. 我可以创建的部分应用函数取决于声明中变量的顺序.例如,您会注意到我无法生成car1988函数.

如何编写允许我使用默认值创建记录的函数?请帮忙.

lef*_*out 15

这就是Haskell 喜欢在库中处理的东西,而不是破解一些硬连线语言支持(这可能会导致各种问题,就像在C++中一样).

import Data.Default

instance Default Car where
  def = Car Nothing Nothing
          -- or whatever you want as the defaults

ford :: Car
ford = def { company = Just "Ford" }
Run Code Online (Sandbox Code Playgroud)

GHCi> ford
Car {company = Just"Ford",year = Nothing}

Default您可以只定义一个,而不是使用该类defaultCar.

data-default如果您的系统中尚未安装cabal ,则可能需要使用cabal进行安装.

  • 除此之外,["智能构造器"](https://wiki.haskell.org/Smart_constructors)(这种构造方式)始终是最好的方式.您可以根据自己喜欢的参数添加任意数量,从模块中导出一些,而不是从模块中导出,如果您的类型是多态的,则可以选择为要处理的每个更具体的类型使用不同的构造函数. (3认同)
  • @dopatraman Nah,只写`defaultCar = Car Nothing Nothing`.然后`ford = defaultCar {company = Just"Ford"}`就像在答案中一样,但名字叫`defaultCar`而不是`def`. (3认同)