在 Haskell 模块中,是否可以导出用于模式匹配的构造函数,但不能用于构造? [英] Is it possible to export constructors for pattern matching, but not for construction, in Haskell Modules?

查看:30
本文介绍了在 Haskell 模块中,是否可以导出用于模式匹配的构造函数,但不能用于构造?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Haskell 中的普通数据类型有零个或多个构造函数,每个构造函数扮演两个角色.

A vanilla data type in Haskell has zero or more constructors, each of which plays two roles.

在表达式中,它支持引入,它是一个从零个或多个参数到数据类型的函数.

In expressions, it supports introduction, its a function from zero or more arguments to the data type.

在模式中,它支持消除,它有点像从数据类型到 Maybe(参数类型的元组)的函数.

In patterns, it supports elimination, its kinda like a function from the data type to Maybe (tuple of argument types).

模块签名是否有可能隐藏前者而暴露后者?

Is it possible for a module signature to hide the former while exposing the latter?

用例是这样的:我有一个类型,T,它的构造函数类型有时可以用来构造无意义的.我有构造函数,可用于构建保证不是无意义的类型的实例.在这种情况下隐藏构造函数是有意义的,但对于调用者来说,能够对他们使用构造函数构建的有保证的非废话进行模式匹配仍然很有用.

The use case is this: I have a type, T, whose constructors types alone can sometimes be used to construct nonsense. I have construction functions which can be used to build instances of the type that are guaranteed not to be nonsense. It would make sense to hide the constructors in this case, but it would still be useful for callers to be able to pattern match over the guaranteed-non-nonsense that they build with the construction functions.

我怀疑这是不可能的,但如果有人有办法做到这一点,我还是会问.

I suspect this is impossible, but in case anyone has a way to do it, I though I would ask.

接下来最好的事情是隐藏构造函数并从 T -> Maybe (This, That), T -> Maybe (The, Other, Thing) 等创建一堆函数

Next best thing is to hide the constructors and create a bunch of functions from T -> Maybe (This, That), T -> Maybe (The, Other, Thing), etc.

推荐答案

您可以使用视图类型视图模式来做您想做的事:

You can use a view type and view patterns to do what you want:

module ThingModule (Thing, ThingView(..), view) where

data Thing = Foo Thing | Bar Int

data ThingView = FooV Thing | BarV Int

view :: Thing -> ThingView
view (Foo x) = FooV x
view (Bar y) = BarV y

请注意,ThingView 不是递归数据类型:所有的值构造器都引用回 Thing.所以现在你可以导出 ThingView 的值构造函数并保持 Thing 抽象.

Note that ThingView is not a recursive data type: all the value constructors refer back to Thing. So now you can export the value constructors of ThingView and keep Thing abstract.

像这样使用:

{-# LANGUAGE ViewPatterns #-}
module Main where

import ThingModule

doSomethingWithThing :: Thing -> Int
doSomethingWithThing(view -> FooV x) = doSomethingWithThing x
doSomethingWithThing(view -> BarV y) = y

箭头符号是 GHC 的视图模式.请注意,它需要语言编译指示.

The arrow notation stuff is GHC's View Patterns. Note that it requires a language pragma.

当然你不需要使用视图模式,你可以手动完成所有的脱​​糖:

Of course you're not required to use view patterns, you can just do all the desugaring by hand:

doSomethingWithThing :: Thing -> Int
doSomethingWithThing = doIt . view
  where doIt (FooV x) = doSomethingWithThing x
        doIt (BarV y) = y

更多

实际上我们可以做得更好一点:没有理由为 ThingThingView

module ThingModule (ThingView(..), Thing, view) where

   newtype Thing = T {view :: ThingView Thing}
   data ThingView a = Foo a | Bar Int

继续像以前一样使用它,但现在模式匹配可以使用FooBar.

Continue useing it the same way as before, but now the pattern matches can use Foo and Bar.

{-# LANGUAGE ViewPatterns #-}
module Main where

import ThingModule

doSomethingWithThing :: Thing -> Int
doSomethingWithThing(view -> Foo x) = doSomethingWithThing x
doSomethingWithThing(view -> Bar y) = y

这篇关于在 Haskell 模块中,是否可以导出用于模式匹配的构造函数,但不能用于构造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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