我有类似以下的内容
data A = A
{ id :: Integer
, foo :: Maybe String
, bar :: Maybe String
, baz :: Maybe String
}
这些数据作为JSON进入我的服务。仅当提供foo
,bar
或baz
中的一个或多个时,此请求才有效。有没有更好的方法在Haskell的类型系统中表达这个?
注意:很遗憾,我无法提出这些单独的请求。我只是遵循一个定义的协议。
答案 0 :(得分:11)
http://hackage.haskell.org/package/these-0.4.2/docs/Data-These.html
import Data.These
data A = A
{ id :: Integer
, fooBarBaz :: These Foo (These Bar Baz)
}
type Foo = String
type Bar = String
type Baz = String
答案 1 :(得分:4)
我会将Map Field String
与data Field = Foo | Bar | Baz
一起使用(如果需要,可以很容易地将其替换为String
,然后执行:
data A = A
{ id :: Integer
, fields :: Map Field String
}
现在检查有效性条件非常简单:
isValid :: A -> Bool
isValid = not . Map.null . fields
答案 2 :(得分:4)
如果foo,bar和baz不是必须有三个单独的字段,我会选择这个,NonEmpty保证至少有一个元素,尽管当然可以有更多。< / p>
import Data.List.NonEmpty
data Impression = Banner String | Video String | Native String
data A = A
{ id :: Integer
, fooBarBaz :: NonEmpty Impression
}
答案 3 :(得分:2)
扩展ʎǝɹɟɟɟǝs建议使用地图:http://mongoosejs.com/docs/api.html#model_Model.find。 (但请注意,这种类型与更受欢迎的非空列表类型there's also a type specifically for non-empty maps冲突。)
import qualified Data.NonEmpty.Map as NEM
data Field = Foo | Bar | Baz
data A = A { id :: Integer
, fields :: NEM.T Field String
}
答案 4 :(得分:2)
考虑为每个可能的必填字段提供一个分支:
data A
= Foo
{ foo :: String
, barM, bazM :: Maybe String
}
| Bar
{ bar :: String
, fooM, barM :: Maybe String
}
| Baz
{ baz :: String
, fooM, barM :: Maybe String
}
这是一个很平常的样板,但它非常直接,非常清楚需要什么。