haskell - 使用 Haskell ADT 成员的构造函数作为类型
问题描述
我有一个像这样的代数数据类型:
type Keyword = Text
data DBField = (:=) Keyword DBVal
deriving (Show, Read, Eq)
data DBVal = VNull
| VInt Int64
| VDouble Double
| VBool Bool
| VString Text
| VUTCTime UTCTime
| VArray [DBVal]
| VObjId ObjectId
| VUUID UUID
| VRecord [DBField]
deriving (Eq, Show, Read)
由于我VRecord
有很多操作,我需要一种定义函数的方法,例如:
get :: VRecord -> Keyword -> Maybe DBVal
get r k = ...
但由于VRecord
是一个数据构造函数,我必须像这样定义我的函数:
get :: DBVal -> Keyword -> Maybe DBVal
get r@(VRecord _) k = ...
get _ _ = ...
这既降低了可读性(主要是在文档中),也迫使我处理其他DBVal
类型的情况。那么处理这种情况的最佳方法是什么?
解决方案
这可以通过 Liquid Haskell 完成:
module DB where
import Data.Text
import Data.Int
import Data.Time
type Keyword = Text
data DBField = (:=) Keyword DBVal
deriving (Show, Read, Eq)
data DBVal = VNull
| VInt Int64
| VDouble Double
| VBool Bool
| VString Text
| VUTCTime UTCTime
| VArray [DBVal]
| VRecord [DBField]
deriving (Eq, Show, Read)
{-@ measure isVRecord @-}
isVRecord (VRecord _) = True
isVRecord _ = False
{-@ type VRecord = {v:DBVal | isVRecord v} @-}
{-@ get :: VRecord -> Keyword -> Maybe DBVal @-}
get :: DBVal -> Keyword -> Maybe DBVal
get (VRecord xs) k = undefined
test :: Maybe DBVal
test = get VNull (pack "test") -- error
在这里试试: http://goto.ucsd.edu:8090/index.html#?demo= permalink%2F1629647897_38731.hs
推荐阅读
- javascript - 如何将字符串添加到 JavaScript 数组中每个元素的开头和结尾?
- javascript - 道具被状态变化覆盖?
- html - Ionicon - Different Sizes, Same CSS
- firebase - 如何使用 Cloud FireStore 查询两个日期范围之间的数据?
- django - rest_framework_jwt | Return custom error message in case of token verification failure
- ios - SwiftUI:如何在不使用几何阅读器的情况下根据框架的大小计算视图的大小?
- dependency-injection - blazor wasm 在 program.cs Main 中注入 IJSRuntime
- c# - 两个不同的类是否有可能具有一个属性——一个类的集合,并且每个对象都知道它属于前两个类中的哪一个?
- google-sheets - 是否可以将多张工作表中的 Google 表格列堆叠到一份报告中?
- python-3.x - 父类值的继承