安全记录字段查询

jam*_*idh 2 haskell

有没有一种干净的方法来避免以下样板:

给定一个记录数据类型定义...。

data Value = A{ name::String } | B{ name::String } | C{}
Run Code Online (Sandbox Code Playgroud)

编写安全返回的函数 name

getName :: Value -> Maybe String
getName A{ name=x } = Just x
getName B{ name=x } = Just x
getName C{} = Nothing
Run Code Online (Sandbox Code Playgroud)

我知道您可以使用Template Haskell做到这一点,我正在寻找一种比这更清洁的解决方案,也许是GHC扩展或其他我忽略的东西。

Ben*_*son 5

lens模板Haskell助手在遇到部分记录字段时会做正确的事情。

{-# LANGUAGE TemplateHaskell #-}


import Control.Applicative
import Control.Lens


data T = A { _name :: String }
       | B { _name :: String }
       | C

makeLenses ''T
Run Code Online (Sandbox Code Playgroud)

这会产生一个Traversal'名为name该选择String内部AB建设者和无助的C情况下。

ghci> :i name
name :: Traversal' T String  -- Defined at test.hs:11:1
Run Code Online (Sandbox Code Playgroud)

因此,我们可以使用^?运算符(这是一个翻转的代名词preview),从Control.Lens.Fold拔出Maybe的名称。

getName :: T -> Maybe String
getName = (^? name)
Run Code Online (Sandbox Code Playgroud)

您还可以使Prism's作为数据类型的构造函数,并使用来选择与之匹配的第一个<|>。当构造函数的字段具有不同的名称时,此版本很有用,但是您一定要记住在添加构造函数时更新提取器函数。

makePrisms ''T

getName' :: T -> Maybe String
getName' t = t^?_A <|> t^?_B
Run Code Online (Sandbox Code Playgroud)

lens 非常有用!