Haskell 在两个不同的模块中定义函数或解决方法
我在模块Haskell 在两个不同的模块中定义函数或解决方法,haskell,ghc,Haskell,Ghc,我在模块a中有一个函数evalExpression::Exp->Value,它严重依赖于参数Exp上的模式匹配 该文件已变得足够大,需要更多的组织。我想将模块A分成模块A.GHC.Num,A.GHC.Types,等等 在GHC中,有没有办法将一个模块内联到另一个模块中?我尝试过这样做,但出现错误“模块导入形成一个循环” 或 有没有办法在两个不同的文件中写入相同的模块 或 我是否可以定义一个函数a.evalExp,该函数尝试(在try-and-catch的意义上)返回a.GHC.Num.
a
中有一个函数evalExpression::Exp->Value
,它严重依赖于参数Exp
上的模式匹配
该文件已变得足够大,需要更多的组织。我想将模块A
分成模块A.GHC.Num
,A.GHC.Types
,等等
- 在GHC中,有没有办法将一个模块内联到另一个模块中?我尝试过这样做,但出现错误“模块导入形成一个循环”
- 有没有办法在两个不同的文件中写入相同的模块
- 我是否可以定义一个函数
,该函数尝试(在try-and-catch的意义上)返回a.evalExp
的值,如果它缓存错误(非穷举模式匹配),则尝试返回a.GHC.Num.evalExp
,以此类推a.GHC.Types.evalExp
我试图解决循环依赖关系,但GHC没有说服我,它说“不明确的事件”。不,你不能在多个文件之间分割模块,当然你也不能在不同的位置定义函数。最接近这一点的是作为类型类一部分的函数,其实例在各种模块中定义。但这可能不是你想要的 但是,可以编译相互递归的模块。理论上,这应该是可行的(tm),但GHC需要一点跳圈来做到这一点;有关详细信息,请参阅。如果您遇到循环模块导入错误,这将使该版本正常工作 没有“好”的方法可以捕获一个取之不尽的模式匹配错误并尝试其他方法。有很多不太好的方法,但你可能不想去那里 如果您的目标是在具有大量实例的单个数据类型上进行模式匹配,那么在不干扰相互递归的模块或类型类的情况下,最简单的方法是在其他模块中使用单独的函数,这些函数将每个构造函数的内容作为直接参数,然后,一个单一的模式匹配模块中的所有案例,该模块导入其他案例并执行分派 假设您有一个类型
Foo
,其大小写为a
,B
,&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
的任何递归调用替换为evalExp
r
evalExp
案例的每个模块。如有必要,请使用限定的导入以避免歧义。定义每个eval函数的列表(它们都应该具有相同的类型),然后定义“real”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
样式的构造替换直接递归,其中组合的递归函数传递给每个(单独的非递归)案例集
这很尴尬,但我不确定有没有更好的办法。也许有一种方法可以使用模板Haskell自动化所有这些废话,但这可能和手动操作一样麻烦
就我个人而言,我可能会咬紧牙关,将所有内容放在一个模块中。我添加了标签haskell,但我不确定该问题是否属于该模块,因为该问题是GHC特有的。如有必要,请删除。关于第一点,一个明显的问题是:您确定无法避免循环导入吗?您能否以某种方式拆分
A
,从而消除循环导入的需要?对于大多数实际用途,Haskell通常可能是GHC特有的。别担心。它无疑是使用最广泛的编译器,大多数时候人们说“Haskell”的意思是“GHC对报告的解释加上一些未指明的GHC扩展”。谢谢你的回答。你能详细说明一下类型类的解决方案吗?我正在匹配包extcore
中的Language.Core.Core.Exp
。我有一些模式匹配表达式,比如evalExp(Var((仅仅是M(P(“base”),[“GHC”],“Num”),“zp”)=代码>用于base和ghc prim中的每个函数bultin。在我看来,问题在于匹配某些字符串。我希望我能在几个文件中匹配类型构造函数Var
。EDIT:我认为可以通过将变量绑定到字符串,然后将包与正则表达式匹配,然后调用适当的eval@CarlosLópez Camey:类型类在这里可能帮不了你,因为你有一个预先存在的数据类型和非常同质的案例。是递归的吗?@camcann。我懂了。。是的,evalExp
是递归的。@CarlosLópez Camey:啊,这让事情变得有点棘手。我会给你举一个可能的解决方案的例子,但我认为无论如何都会很尴尬。@CAMcCann:再次感谢你的洞察力。使用evalExpCases
的解决方案肯定比使用额外的正则表达式匹配要快得多。