类型系统中的强制Maybes

时间:2015-08-10 13:29:43

标签: haskell

我有类似以下的内容

data A = A
  { id :: Integer
  , foo :: Maybe String
  , bar :: Maybe String
  , baz :: Maybe String
  }

这些数据作为JSON进入我的服务。仅当提供foobarbaz中的一个或多个时,此请求才有效。有没有更好的方法在Haskell的类型系统中表达这个?

注意:很遗憾,我无法提出这些单独的请求。我只是遵循一个定义的协议。

5 个答案:

答案 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 Stringdata 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
        }

这是一个很平常的样板,但它非常直接,非常清楚需要什么。