如何在Haskell中构造受约束的参数?

时间:2018-07-20 22:16:05

标签: haskell typeclass template-haskell

我想在Haskell中构建一个大型架构。成分采用参数,并且参数受约束。例如,我可能决定一个圆采用一个称为Radius的参数,该参数被约束为非负数。我将全局定义参数,因为每个参数可以由多个组成部分使用。参数可能有数百个,其中许多将具有难以键入的长名称。

我有各种各样的解决方案,但是参数声明是重复的,我想简化它们。我对“简单”的标准只是为了最大程度地减少必须键入参数名称的次数。其中一部分是简化参数定义本身。另一个是如果可能的话,避免在创建数据对象时键入参数名称。因此,无需真正键入“ 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. 我认为可以使用Template Haskell来定义参数(例如Radius),而无需重复名称。您会推荐这种方法吗?

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

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

1 个答案:

答案 0 :(得分:1)

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

并不难
subtype "Radius" 'Float [| \x -> x >= 0 |]

您说过可能有数百种这样的事情,这在我脑海中引发了设计警报。在这一点上,我会非常努力地寻找机会,以将更多概念抽象添加到您的架构中-太多了。但是如果没有更多信息和上下文,我只能说真的:当心!