在私有数据构造函数上进行模式匹配 [英] Pattern matching on a private data constructor
问题描述
我正在为网格轴编写一个简单的ADT。在我的应用程序中,网格可能是正常的(在坐标之间有一个固定的步长),或者不规则(否则)。当然,规则网格只是一个不规则网格的特殊情况,但在某些情况下可能需要区分它们(例如,执行一些优化)。所以,我宣布我的ADT如下:
$ p $ data $ GridAxis = RegularAxis(Float,Float)Float - (min,max )delta
| IrregularAxis [Float] - [xs]
但我不希望用户创建格式不正确的轴 max <分钟
或无序 xs
列表。因此,我添加了更智能的构造函数,它们执行一些基本检查: p>
regularAxis ::(Float,Float) - >浮动 - > GridAxis
regularAxis(a,b)dx = RegularAxis(min a b,max a b)(abs dx)
irregularAxis :: [Float] - > GridAxis
irregularAxis xs = IrregularAxis(sort xs)
我不希望用户创建所以我不会在模块导出列表中添加 GridAxis
数据构造函数:
module GridAxis(
GridAxis,
regularAxis,
irregularAxis,
)其中
但事实证明,完成这一步之后,我无法再对 GridAxis
使用模式匹配。尝试使用它
将合格的GridAxis导入为GA
test :: GA.GridAxis - > Bool
测试轴=
的情况轴GA.RegularAxis - >真
GA.IrregularAxis - >假
给出以下编译器错误:
src / Physics / ImplicitEMC.hs:7:15:
不在范围内:数据构造函数`GA.RegularAxis'
src / Physics / ImplicitEMC.hs:8:15:
不在范围内:数据构造函数GA.IrregularAxis'
有什么可以解决这个问题吗?
您可以定义构造函数模式的同义词。这可以让你使用相同的名字进行智能建设和哑模式匹配。
{ - #LANGUAGE PatternSynonyms# - }
模块GridAxis(GridAxis,模式RegularAxis,模式IrregularAxis)其中
导入Data.List
数据GridAxis = RegularAxis_(Float,Float)Float - (min,最大)增量
| IrregularAxis_ [Float] - [xs]
- 带有& - 的行定义匹配行为
- 带=的行定义构造函数行为
模式RegularAxis minmax delta < - RegularAxis_minmax delta其中
RegularAxis(a,b)dx = RegularAxis_(minab,maxab)(absdx)
pattern IrregularAxis xs < - IrregularAxis_ xs其中
IrregularAxis xs = IrregularAxis_(sort xs)
现在你可以这样做:
module Foo
导入GridAxis
foo :: GridAxis - > a
foo(RegularAxis(a,b)d)= ...
foo(IrregularAxis xs)= ...
并且使用 RegularAxis
和 IrregularAxis
作为智能构造函数。
I'm writing a simple ADT for grid axis. In my application grid may be either regular (with constant step between coordinates), or irregular (otherwise). Of course, the regular grid is just a special case of irregular one, but it may worth to differentiate between them in some situations (for example, to perform some optimizations). So, I declare my ADT as the following:
data GridAxis = RegularAxis (Float, Float) Float -- (min, max) delta
| IrregularAxis [Float] -- [xs]
But I don't want user to create malformed axes with max < min
or with unordered xs
list. So, I add "smarter" construction functions which perform some basic checks:
regularAxis :: (Float, Float) -> Float -> GridAxis
regularAxis (a, b) dx = RegularAxis (min a b, max a b) (abs dx)
irregularAxis :: [Float] -> GridAxis
irregularAxis xs = IrregularAxis (sort xs)
I don't want user to create grids directly, so I don't add GridAxis
data constructors into module export list:
module GridAxis (
GridAxis,
regularAxis,
irregularAxis,
) where
But it turned out that after having this done I cannot use pattern matching on GridAxis
anymore. Trying to use it
import qualified GridAxis as GA
test :: GA.GridAxis -> Bool
test axis = case axis of
GA.RegularAxis -> True
GA.IrregularAxis -> False
gives the following compiler error:
src/Physics/ImplicitEMC.hs:7:15:
Not in scope: data constructor `GA.RegularAxis'
src/Physics/ImplicitEMC.hs:8:15:
Not in scope: data constructor `GA.IrregularAxis'
Is there something to work this around?
You can define constructor pattern synonyms. This lets you use the same name for smart construction and "dumb" pattern matching.
{-# LANGUAGE PatternSynonyms #-}
module GridAxis (GridAxis, pattern RegularAxis, pattern IrregularAxis) where
import Data.List
data GridAxis = RegularAxis_ (Float, Float) Float -- (min, max) delta
| IrregularAxis_ [Float] -- [xs]
-- The line with "<-" defines the matching behavior
-- The line with "=" defines the constructor behavior
pattern RegularAxis minmax delta <- RegularAxis_ minmax delta where
RegularAxis (a, b) dx = RegularAxis_ (min a b, max a b) (abs dx)
pattern IrregularAxis xs <- IrregularAxis_ xs where
IrregularAxis xs = IrregularAxis_ (sort xs)
Now you can do:
module Foo
import GridAxis
foo :: GridAxis -> a
foo (RegularAxis (a, b) d) = ...
foo (IrregularAxis xs) = ...
And also use RegularAxis
and IrregularAxis
as smart constructors.
这篇关于在私有数据构造函数上进行模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!