将SML代码转换为Haskell的几个基本问题 1)我习惯于在SML代码中使用本地嵌入式表达式,例如测试表达式,打印等,它们在加载(评估)代码时对本地测试和输出起作用。 在Haskell中,似乎获得结果(评估)的唯一方法是在模块中添加代码,然后转到另一个模块中的main并添加一些内容来调用和打印结果。
这是对的吗?在GHCi中,我可以输入表达式并查看结果,但这可以自动化吗? 每次测试评估都必须进入顶级主要部分对我来说似乎不方便 - 可能只需要改变我的懒惰模式。
2)在SML中,我可以对返回的结果进行模式匹配和统一,例如:
val myTag(x) = somefunct(a,b,c);
并在匹配后获得x的值。
我可以轻松地在Haskell中做类似的事情,而无需编写单独的提取函数吗?
3)如何使用元组参数进行构造函数,即未经证实 在SML:
数据类型Thing = Int * Int的信息;
但是在Haskell,我试过了;
数据Thing = Info(Int Int)
失败了。 (“Int应用于类型中的太多参数:一些Int Int”) 咖喱版很好,
数据Thing = Info Int Int
但我想要没有咖喱。
感谢。
答案 0 :(得分:5)
如果是将调试和跟踪插入纯代码,通常只需要调试。要在Haskell中执行此操作,您可以使用Debug.Trace.trace
,in the base package。
如果您担心调用函数,Haskell程序将按照依赖顺序从main
向下计算。但是,在GHCi中,您可以导入模块并调用您希望的任何顶级函数。
如果您愿意,可以将原始参数返回给函数,方法是将其作为函数结果的一部分,例如:有一个元组:
f x = (x, y)
where y = g a b c
或者你的意思是返回一个值或另一个值?然后使用标记的union(sum-type),例如Either
:
f x = if x > 0 then Left x
else Right (g a b c)
使用(,)
构造函数。 E.g。
data T = T (Int, Int)
虽然更像Haskell,但是:
data T = T Int Bool
那些应该是实践中的严格字段:
data T = T !Int !Bool
答案 1 :(得分:4)
Debug.Trace
允许您内联打印调试消息。但是,由于这些函数使用unsafePerformIO
,因此与SML等按值调用语言相比,它们可能会以意想不到的方式运行。
我认为@
语法是您在这里寻找的:
data MyTag = MyTag Int Bool String
someFunct :: MyTag -> (MyTag, Int, Bool, String)
someFunct x@(MyTag a b c) = (x, a, b, c) -- x is bound to the entire argument
在Haskell中,元组类型用逗号分隔,例如(t1, t2)
,所以你想要的是:
data Thing = Info (Int, Int)
答案 2 :(得分:1)
对于#2,是的,Haskell的模式匹配做同样的事情。 let
和where
都进行模式匹配。你可以做到
let MyTag x = someFunct a b c
in ...
或
...
where MyTag x = someFunct a b c
答案 3 :(得分:1)
阅读其他答案,我想我可以提供更多示例和一个建议。
data ThreeConstructors = MyTag Int | YourTag (String,Double) | HerTag [Bool]
someFunct :: Char -> Char -> Char -> ThreeConstructors
MyTag x = someFunct 'a' 'b' 'c'
这就像“让MyTag x = someFunct a b c”示例,但它是模块的顶层。
正如您所注意到的,Haskell的顶级可以定义命令,但是由于您的模块已被另一个模块导入,因此无法自动运行任何代码。这与Scheme或SML完全不同。在Scheme中,文件被解释为逐个表单执行,但Haskell的顶级只是声明。因此,库在加载时不能像运行初始化代码那样做正常的事情,它们必须提供“pleaseRunMe :: IO()”类命令来进行任何初始化。
正如您所指出的那样,这意味着运行所有测试需要一些样板代码来列出所有测试。您可以查看hackage的Testing组,以便图书馆提供帮助,例如test-framework-th。