在私有数据构造函数上进行模式匹配 [英] Pattern matching on a private data constructor

查看:167
本文介绍了在私有数据构造函数上进行模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为网格轴编写一个简单的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆