我想在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
您能建议一种更好的方法来构造此代码吗?
我认为可以使用Template Haskell来定义参数(例如Radius),而无需重复名称。您会推荐这种方法吗?
是否可以为值编写默认规则?天真的,我想
匹配模式value (_ x)
,但是类型不正确。
有什么方法可以完成同一件事?
是否有更简单的方法将值与类型相关联?例如,
半径具有与类型相关联的约束,但似乎没有必要
必须构造半径来获得其约束。当我尝试写
constraint :: Constraint
,GHC抱怨类型参数a
是
不使用。
答案 0 :(得分:1)
听起来您希望Haskell能够从谓词中声明子类型。可以使用smart constructors来完成,但确实如此,其中涉及一些样板。我认为Template Haskell并不是一个坏主意。将智能构造函数的定义包装成类似
并不难subtype "Radius" 'Float [| \x -> x >= 0 |]
您说过可能有数百种这样的事情,这在我脑海中引发了设计警报。在这一点上,我会非常努力地寻找机会,以将更多概念抽象添加到您的架构中-太多了。但是如果没有更多信息和上下文,我只能说真的:当心!