如何在多行中定义ghci中的函数?

Pet*_*McG 146 haskell ghci

我正在尝试定义任何跨越ghci中多行的简单函数,以下面的示例为例:

let abs n | n >= 0 = n
          | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已尝试在第一行后按Enter键:

Prelude> let abs n | n >= 0 = n
Prelude>           | otherwise = -n
<interactive>:1:0: parse error on input `|'
Run Code Online (Sandbox Code Playgroud)

我也尝试过使用:{:}命令但是我没有做到这一点:

Prelude> :{
unknown command ':{'
use :? for help.
Run Code Online (Sandbox Code Playgroud)

我在Linux上使用GHC Interactive版本6.6 for Haskell 98,我缺少什么?

kar*_*kfa 240

GHCi现在具有多线输入模式,启用:set + m.例如,

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800
Run Code Online (Sandbox Code Playgroud)

  • 设置多行模式使得`ghci`在这方面的行为与Python解释器非常相似.很方便!实际上你可以在你的主目录中创建一个`.ghci`文件,在其中放置`:set + m`,每次启动`ghci`时多行模式将成为默认模式! (36认同)
  • 你可以*完全*使用尾随的'let`来避免缩进.只需键入一个`let`后跟换行符:`let`⏎.然后`fac 0 =1`⏎.然后`fac n = n*fac(n-1)`⏎⏎,你就完成了! (11认同)
  • 要防止Prelude出现在延续行上,还要在.ghci中添加:set prompt2"|". (4认同)
  • 这真的很棒.但是我注意到当我使用`:set prompt"λ"`设置我的提示时,连续的行说"Prelude"而不是"λ".有办法解决这个问题吗? (2认同)
  • 请参阅此处以获取用于定义新延续提示的修补程序https://ghc.haskell.org/trac/ghc/ticket/7509#no1 (2认同)
  • `:set Prompt2 "| "` 现在似乎是 `:set Prompt-cont "| "`。不确定何时进行更改,但我正在使用 GHC 8.6.3。 (2认同)

new*_*cct 122

对于守卫(就像你的例子),你可以将它们全部放在一条线上并且它可以工作(守卫不关心间距)

let abs n | n >= 0 = n | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

如果你想用你在参数上模式匹配的多个定义来编写你的函数,就像这样:

fact 0 = 1
fact n = n * fact (n-1)
Run Code Online (Sandbox Code Playgroud)

然后你会使用分号分隔定义的大括号

let { fact 0 = 1 ; fact n = n * fact (n-1) }
Run Code Online (Sandbox Code Playgroud)


Jus*_*ley 57

丹是正确的,但:{:}必须在每个出现在自己的行:

> :{ 
> let foo a b = a +
>           b
> :}
> :t foo
foo :: (Num a) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

这也与布局规则交互,因此在使用do-notation时,可能更容易明确地使用大括号和分号.例如,此定义失败:

> :{
| let prRev = do
|   inp <- getLine
|   putStrLn $ reverse inp
| :}
<interactive>:1:18:
    The last statement in a 'do' construct must be an expression
Run Code Online (Sandbox Code Playgroud)

但是当添加括号和分号时它会起作用:

> :{
| let prRev = do {
|   inp <- getLine;
|   putStrLn $ reverse inp;
| }
| :}
> :t prRev
prRev :: IO ()
Run Code Online (Sandbox Code Playgroud)

只有从文件中粘贴定义(缩进可能会发生变化)时,这才真正重要.


Dan*_*Dan 18

它看起来像:{:}是一个相当新的功能.您可能需要升级GHC.

编辑:已确认,请参阅http://www.haskell.org/ghc/docs/6.8.2/html/users_guide/release-6-8-2.html


C. *_*ann 7

如果你不想升级GHC只为:{:},你需要它写在一行:

> let abs' n | n >= 0 = n | otherwise = -n
Run Code Online (Sandbox Code Playgroud)

我不知道Haskell中的任何单一定义必须写在多行上.以上确实在GHCi中有效:

> :t abs'
abs' :: (Num a, Ord a) => a -> a
Run Code Online (Sandbox Code Playgroud)

对于其他表达式,例如do块,您需要使用带有花括号和分号的非布局语法(eugh).