Haskell脚本中的任何内容都可以在GHCi会话中复制吗



我想运行函数

act :: IO(Char, Char)
act = do x <- getChar
getChar
y <- getChar
return (x,y)

在GHCi会话中交互。我在其他地方看到,您可以通过使用分号来替换换行符来定义会话中的函数。然而,当我写时

act :: IO(Char, Char); act = do x <- getChar; getChar; y <- getChar; return (x,y)

它不编译,说

parse error on input ‘;’

我在其他地方看到:{ ... }:可以用于多行命令,但键入

:{ act :: IO(Char, Char)

然后点击回车键会导致一个错误——也许我误解了如何使用它们。

除了让这个特殊的案例发挥作用之外,是否有一种通用的方法可以获取在Haskell脚本中运行的代码,并使其在交互式会话中运行?

您不能仅仅插入分号来替换每个换行符。在一行中执行操作意味着选择退出布局规则,因此您必须插入自己的分号和大括号。这意味着您需要知道在没有布局规则的情况下,哪些地方需要大括号和分号。特别是在这种情况下,每个do块都需要在整个块周围使用大括号,每个操作之间使用分号。布局规则通常会根据缩进为您插入这些内容。

因此,要在一行中写下这个特定的例子,你可以这样做:

let act :: IO(Char, Char); act = do {x <- getChar; getChar; y <- getChar; return (x,y)}

在足够新的ghci版本上,您也可以省略let

对于足够简单的do块,您甚至可以省略大括号。在您的示例中,{}可能只有一个位置,因此即使您在一行中执行所有操作,GHCI也会插入它们。但是,对于具有多个do块或其他多行构造的表达式,如果希望它们位于一行,则需要显式插入它们。

关于更广泛的问题:

除了让这个特殊的案例发挥作用之外,是否有一种通用的方法可以获取在Haskell脚本中运行的代码,并使其在交互式会话中运行?

据我所知,最接近的是使用多行分隔符":{:}(每一行都有自己的一行("。他们几乎可以处理你扔给他们的任何东西。它们不能处理导入(GHCi确实支持完整的导入语法,但每个导入都必须在一行中单独存在(和杂注(唯一的替代方案是:set,它也需要一行(,这意味着你不得不将它们与代码的其余部分分开,并预先输入它们。

(你总是可以把代码保存在某个地方,然后用:l加载文件,这通常是更方便的选择。不过,我对:{:}有一个弱点——如果我只想尝试六行没有上下文的即兴代码,我倾向于打开一个文本编辑器窗口,写下小片段,然后直接粘贴到GHCi中。(

最新更新