代码之家  ›  专栏  ›  技术社区  ›  Peter McG

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

  •  142
  • Peter McG  · 技术社区  · 14 年前

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

    let abs n | n >= 0 = n
              | otherwise = -n
    

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

    Prelude> let abs n | n >= 0 = n
    Prelude>           | otherwise = -n
    <interactive>:1:0: parse error on input `|'
    

    我还尝试使用 :{ :} 命令,但我走不远:

    Prelude> :{
    unknown command ':{'
    use :? for help.
    

    我在Linux上使用haskell 98的ghc交互版本6.6,我缺少什么?

    5 回复  |  直到 11 年前
        1
  •  115
  •   newacct    14 年前

    对于防护装置(如您的示例),您可以将它们全部放在一行上,它可以工作(防护装置不关心间距)。

    let abs n | n >= 0 = n | otherwise = -n
    

    如果要用多个定义编写函数,这些定义与参数上的模式匹配,如下所示:

    fact 0 = 1
    fact n = n * fact (n-1)
    

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

    let { fact 0 = 1 ; fact n = n * fact (n-1) }
    
        2
  •  227
  •   Mark Reed    11 年前

    ghci现在有一个多行输入模式,使用:set+m启用。例如,

    Prelude> :set +m
    Prelude> let fac 0 = 1
    Prelude|     fac n = n * fac (n-1)
    Prelude|
    Prelude> fac 10
    3628800
    
        3
  •  50
  •   Justin Bailey    14 年前

    丹是对的,但是 :{ :} 必须在各自的行中显示:

    > :{ 
    > let foo a b = a +
    >           b
    > :}
    > :t foo
    foo :: (Num a) => a -> a -> a
    

    这也与布局规则交互,因此当使用do符号时,显式使用大括号和分号可能更容易。例如,此定义失败:

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

    但是,当加上大括号和分号时,它会起作用:

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

    这只在从文件粘贴定义时才真正重要,因为缩进可能会更改。

        4
  •  17
  •   Dan    14 年前

    看起来像 :{ :} 是一个很新的功能。您可能需要升级GHC。

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

        5
  •  7
  •   C. A. McCann Ravikant Cherukuri    14 年前

    如果您不想升级GHC :{ :} ,您需要将所有内容都写在一行上:

    > let abs' n | n >= 0 = n | otherwise = -n
    

    我不知道哈斯克尔的任何一个定义 必须 写在多行上。以上确实适用于GHCI:

    > :t abs'
    abs' :: (Num a, Ord a) => a -> a
    

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