Haskell使用镜头记录默认值而不使用_

时间:2016-06-28 03:21:24

标签: haskell

我正在尝试使用默认值创建记录,并避免在制作记录时使用下划线。我目前正在使用:

data SectionedItems s i = SectionedItems{
    _section :: Maybe s,
    _items :: [i],
    _subsections :: [SectionedItems s i]
}
makeLenses ''SectionedItems

sectionedItems = SectionedItems{
    _section = Nothing,
    _items = [],
    _subsections = []
}

-- Create Instance of SectionedItems
sectionedItems
    & section .~ Just x

是否有更短或更清晰的方法来制作具有默认值且没有下划线的记录?

1 个答案:

答案 0 :(得分:2)

有一个名为data-default的方便包,它定义了一个类型Default,它公开了一个函数def :: a - 一个默认值。此外,虽然我似乎无法找到任何文档,但您可以自动派生它(使用正确的标志和导入的东西)。当然,如果您的默认值必须不同,您可以自己声明实例。

然后,您可以通过以下方式缓解示例中的一些痛苦:

{-# LANGUAGE DeriveGeneric, DeriveAnyClass, TemplateHaskell #-}

import Data.Default
import GHC.Generics
import Control.Lens

data SectionedItems s i = SectionedItems{
    _section :: Maybe s,
    _items :: [i],
    _subsections :: [SectionedItems s i]
} deriving (Generic,Default)
makeLenses ''SectionedItems

-- Create a SectionedItems - this could have whatever type you want
def & section .~ Just 3 :: SectionedItems Int [String]

(尽量不要使用'实例'就像你在OOP中那样,因为Haskell的含义非常不同)。

然而,这并没有取消Lens中的下划线。我不确定你可以为此做些什么。最重要的是,makeLenses''函数生成的函数不能与Haskell在创建记录时为您生成的函数进行名称冲突。通过查看Control.Lens.TH你可以看到你可以调节镜头名称是你想要的,但底线你将不得不采用一种惯例 - 记录存取器的下划线和镜头没有下划线是一个好的惯例如任何。

修改

如果要显式定义默认值,请创建Default的实例:

instance Default (SectionedItems s i) where
  def = SectionedItems { _section = Nothing, _items = [], _subsections = [] }