我正在用Haskell编写一个模块,我想创建这个模块的两个版本:
为方便起见,我希望这两个模块(有两个不同的名称)共享相同的源文件。这两个模块将具有相同的类型和相同的功能,但有一些差异('扩展'版本将依赖于' basic' one。)
我的想法是拥有这样的东西:
$sb = [scriptblock]::Create("`$text = `$Event.SourceEventArgs.Data; `$OUTFIL = `$Event.MessageData; Add-Content $OUTFIL.out `$text")
使用一些给GHC / Cabal的编译指令构建这两个模块。
是否可以使用Haskell进行此类操作?
什么是GHC / Cabal编译指令,可用于进行条件构建?
答案 0 :(得分:1)
您不能将两个模块放在同一个文件中。但是你可以通过一些重新导出来获得你想要的东西。
一个文件同时包含基本代码和扩展代码(我稍微缩短了一点):
module MyLibExt where
MyType = TypeA | TypeB | TypeC | TypeExtendedD | TypeExtendedE
myFunction TypeA = ...
myFunction TypeB = ...
myFunction TypeExtendedD = ...
然后另一个文件将是基本文件:
module MyLib (MyType (TypeA, TypeB, TypeC), myFunction)
import MyLibExt
这样,如果有人只导入MyLib
,他们只能访问基本构造函数,而不能访问扩展构造函数。 myFunction
仍会像TypeExtendedD
一样处理MyLibExt
值,但由于我们无法仅使用MyLib
创建这些值,因此module Example (
exampleFunction, -- simply export this function.
ExampleType1 (), -- export the type, but no constructors.
ExampleType2 (ExampleConstructor1, ExampleConstructor2), -- export the given type and its given constructors. You can't export constructors like functions, you have to do it like this).
ExampleType3 (..), -- export given type and all its constructors.
ExampleClass1, -- export type class, but no functions that belong to it.
ExampleClass2 (exampleFunction2, exampleFunction3), -- export type class and the given functions belonging to it. You can also export these functions as though they were normal functions, like in the first of the examples.
ExampleClass3 (..), -- export type class and all its functions.
module Module1, -- re-export anything that is imported from Module1.
) where
细
更一般地说,在定义模块时,您可以说明要导出的内容。以下是一些基本示例:
x &= -x
您可以导出范围内的任何内容,包括从其他模块导入的任何内容。实际上,如果要从其他模块重新导出某些内容,则需要显式定义这样的导出列表,默认情况下它只会导出此模块中定义的内容。
答案 1 :(得分:0)
考虑抽象。它可能不值得,但有时隐藏着美丽和力量,它只能被抽象化。对于您的案例MyType
和MyFunction
,也许就是这样(只是一个示例,根据您的详细信息,它可能看起来非常不同):
class MyFunction a where
myFunction :: a -> Int
data MyType = TypeA | TypeB | TypeC
instance MyFunction MyType where
myFunction TypeA = 0
myFunction TypeB = 1
myFunction TypeC = 2
data MyTypeExt = Orig MyType | TypeExtendedD | TypeExtendedE
instance MyFunction MyTypeExt where
myFunction (Orig x) = myFunction x
myFunction TypeExtendedD = myFunction TypeC + 1
myFunction TypeExtendedE = myFunction TypeC + 2
那将是第一级。您可以更进一步,使扩展参数化:
data MyTypeExt a = Orig a | TypeExtendedD | TypeExtendedE
instance (MyFunction a) => MyFunction (MyTypeExt a) where
... -- defined so that it works for any myFunction-able Orig
然后很容易分成不同的文件。但抽象的优势远不止将事物分解为公共和私人空间。如果您的代码有两个“有效”版本,则这两个版本各自具有一致的含义。找到它们的共同点,看看你是否可以编码它们的共同点,而不是特别参考任何一个。然后仔细看看 - 这两个例子有什么共同之处?你能用更简单的部分构建你的两个例子吗?在Haskell中,代码编程你。