我应该如何在 Haskell 中构造约束参数?

How should I structure constrained parameters in Haskell?

我想在 Haskell 中构建一个大架构。成分带参数,参数受约束。例如,我可能会决定圆采用一个称为半径的参数,该参数被限制为非负数。我将全局定义参数,因为每个参数都可以由多个成员使用。可能有数百个参数,而且许多参数的名称很长,难以键入。

我有一个解决方案,但是参数声明是重复的,我想简化它们。我对 "simple" 的标准只是为了尽量减少必须键入参数名称的次数。其中一部分是简化参数定义本身。另一个是尽可能避免在创建数据对象时键入参数名称。因此,应该能够在不实际键入 "Radius".

的情况下构造一个 Circle

下面是代码,后面是一些更具体的问题。在此先感谢您的帮助!

data Constraint = Constraint
test :: Float -> Constraint -> Bool
test _ _ = undefined
--
nonnegative :: Constraint
nonnegative = undefined
--
data Expr = Constant Float -- | Variable String | Add Parameter Parameter ...
eval (Constant x) = x
--
class Parameter a where
  value :: a -> Float
  constraint :: a -> Constraint
  validate :: a -> Bool
  validate x = test (value x) (constraint x)

-- Schema.  Expecting dozens of constituents with many parameters existing
-- in complex relationships.
data Shape = Circle Radius
--
-- There may be hundreds of parameters like Radius, many with long,
-- difficult-to-type names.
data Radius = Radius Expr
instance Parameter Radius where
  constraint _ = nonnegative
  value (Radius r) = eval r
  1. 你能建议一个更好的方法来构建这段代码吗?

  2. 我认为模板 Haskell 可用于定义参数(如 Radius)而无需重复名称。您会推荐这种方法吗?

  3. 是否可以写一个默认值的规则?天真地,我想 匹配模式 value (_ x),但它的类型当然不正确。 有什么方法可以完成同样的事情吗?

  4. 是否有更简单的方法将值与类型相关联?例如, Radius 有一个与类型相关的约束,但似乎没有必要 必须构造一个 Radius 来获得它的约束。当我尝试写 constraint :: Constraint,GHC 抱怨类型参数 a 是 没用过。

听起来您希望 Haskell 能够从谓词声明子类型。这可以用 smart constructors 来完成,但这是真的,其中涉及一些样板文件。我不认为模板 Haskell 是个坏主意。将智能构造函数的定义包装成

这样的东西并不难
subtype "Radius" 'Float [| \x -> x >= 0 |]

你说这些东西可能有几百个,这在我心中引起了设计警报。在这一点上,我会非常努力地寻找机会为您的架构添加更多概念抽象 — 数百个太多了。但是没有更多信息和上下文,我只能说:当心!