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