Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell使用不带镜头的镜头记录默认值__Haskell - Fatal编程技术网

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

Haskell使用不带镜头的镜头记录默认值_,haskell,Haskell,我试图用默认值制作记录,并在制作记录时避免使用下划线。我目前正在使用: data SectionedItems s i = SectionedItems{ _section :: Maybe s, _items :: [i], _subsections :: [SectionedItems s i] } makeLenses ''SectionedItems sectionedItems = SectionedItems{ _section = Nothing,

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

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

有没有一种更短或更清晰的方法来创建带有默认值且不带下划线的记录?

有一个名为的方便包,它定义了一个typeclass
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中那样使用“instance”,因为Haskell的含义与“instance”截然不同)

然而,这并不能消除
镜头中的下划线。我不知道你能为此做些什么。底线是,为您生成的函数
makelents'
不能与Haskell在创建记录时为您生成的函数名称冲突。通过查看,您可以看到您可以将镜头名称调整为您想要的名称,但底线是您必须确定一个约定-下划线用于记录访问器,而没有下划线用于镜头,这是一个很好的约定

编辑 如果要明确定义默认值,请创建
default

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

您可能想看看我使用的另一个约定,即使用数据类型前缀命名所有记录字段标签,如
sectionedItemsSections
中所示。Control.Lens.TH中的至少一些选项将去掉生成的镜头名称的前缀,这对于为多个数据类型重载的镜头使用
makeFields
很好(因为它还可以防止记录字段标签冲突,尽管它们现在非常冗长).您不需要使用
TemplateHaskell
语言扩展来让镜头工作吗?@klappvisor,使用方便的
MakeLens
等功能,是的。若要手动书写并使用镜头,编号@2426021684,请让我检查一下。我应该在输入之前尝试一下那个实例。