2013-02-14 32 views
2

我在模块A中有一个函数evalExpression :: Exp -> Value,它很大程度上依赖于参数Exp上的模式匹配。在两个不同的模块中定义一个函数,或者一个解决方法

该文件已经变得足够大,希望有更多的组织。我想分裂模块A成模块A.GHC.NumA.GHC.Types

  • 有没有办法来内联内另一个在GHC的模块?我试图这样做,但我得到的错误“模块导入形成循环”

  • 有没有写在两个不同的文件在同一模块的方法吗?

  • 我可以定义一个函数A.evalExp试图(在try和catch的意义上)返回的A.GHC.Num.evalExp值,如果缓存错误(非详尽模式匹配)试图返回A.GHC.Types.evalExp,等等?

更新

我试图解决循环依赖,但GHC是不服气,它说: “发生暧昧”。

+0

我加了标签haskell,但我不确定问题属于那里,因为问题是GHC特定的。如有必要,请删除。 – 2013-02-14 15:54:47

+1

关于第一点的一个显而易见的问题:你确定你无法避免循环进口吗?你能以某种方式拆分'A'以消除循环进口的需要吗? – gspr 2013-02-14 16:01:33

+0

对于大多数实际用途,Haskell一般也可能是GHC特定的。不要担心。它是遥遥领先的最广泛使用的编译器,大多数时候人们说“Haskell”时,他们真正的意思是“GHC对报告的解释以及一些未指定的GHC扩展”。 – 2013-02-14 16:04:05

回答

5

不,你不能在多个文件之间分割一个模块,而且你当然不能在不同的位置定义一个函数。最接近这个的是一个函数,它是类型类的一部分,实例在各个模块中定义。但这可能不是你想要的。

但是,它可能编译相互递归模块。理论上这应该是Just Work(tm),但是GHC需要一些箍跳才能做到;详情请参阅the User's Guide。如果您正在获取循环模块导入错误,则应该让您可以使用该版本。

有没有“好”的方式来捕捉一个无尽的模式匹配错误,并尝试别的。有很多不太好的方法,但你可能不想去那里。

如果你的目标是对具有大量情况的单一数据类型进行模式匹配,那么最直接的方式就是将相互分离的模块或类型分解出来,而不是混淆相互递归的模块或类型类,将每个构造函数的内容作为直接参数,然后在导入其他模块的所有情况下进行单个模式匹配并执行分派。

假设您有一个类型Foo与案件AB,& c。,与相似命名的模块。在“中央”模块中,您可以有:

doStuff (A x y) = A.doStuffA x y 
doStuff (B z) = B.doStuffB z 

...等等。

在某些情况下,以类似方式拆分整个数据类型甚至是有意义的,并为每个构造函数创建一个单独的类型,例如:data Foo = A FooA | B FooB | ...。当你有多种可能以多种方式相互递归的复杂数据类型时,这是最有用的,典型的例子是AST。


好的,这里有一种方法来模拟你想要的东西而不做任何过于粗略的事情。

首先,按照理想的方式将功能分成不同的模块。然后进行以下更改:

  • 更改结果类型使用Maybe,包装导致Just和增加产生Nothing一个包罗万象的默认情况。

  • 添加额外参数r,并用r替换递归调用evalExp

从中央模块导入包含evalExp个案的每个模块。如有必要,请使用合格的导入以避免含糊不清。定义每个eval函数列表(他们都应该有相同的类型),然后定义了“真实”的evalExp因为这样的事情:

expCases = [A.GHC.Num.evalExp, A.GHC.Types.evalExpr {- etc... -} ] 

evalExpCases exp = mapMaybe (\eval -> eval evalExp exp) expCases 

evalExp exp = case evalExpCases exp of 
        (r:_) -> -- use the first result 
        [] -> -- no cases matched 

从本质上讲,这是使用Maybe明确表示穷尽性的图案,并更换使用fix风格的构造的直接递归,其中将组合的递归函数传递给每个(单独的非递归)案例。

这很尴尬,但我不确定有没有更好的方法。可能有一种方法可以使用Template Haskell自动化所有这些垃圾,但这可能与手动操作一样麻烦。

就我个人而言,我可能只是咬紧牙关,把它留在一个模块中。

+0

谢谢你的回答。你能否详细说明类型解决方案?我通过'extcore'包匹配'Language.Core.Core.Exp'。并且我有模式匹配表达式,比如'evalExp(Var((Just(M(P(“base”),[“GHC”],“Num”))),“zp”))= ..'对于每个函数bultin在基地和ghc基。所以问题是,在我看来,在某些字符串上是匹配的。我希望我可以在几个文件中匹配类型构造函数'Var'。 编辑:我认为这可以通过绑定变量到字符串,然后用正则表达式匹配包,然后调用适当的eval – 2013-02-14 16:44:01

+0

@CarlosLópez-Camey:类型类可能不会帮助你在这里,因为你有一个预先存在的数据类型和非常均匀的情况。 evalExp是递归的吗? – 2013-02-14 16:51:19

+0

@CAMcCann。我明白了。是的,'evalExp'是递归的。 – 2013-02-14 16:53:29

相关问题