web-dev-qa-db-ja.com

ghciで複数行にわたって関数を定義する方法は?

私は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 Interactiveバージョン6.6を使用していますが、何が欠けていますか?

143
Peter McG

ガードの場合(例のように)、それらをすべて1行に置くだけで機能します(ガードは間隔を気にしません)

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) }
117
newacct

GHCiには、複数行入力モードがあり、:set + mで有効になります。例えば、

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800
235
karakfa

ダンは正しいですが、:{および:}は、それぞれ独自の行に表示する必要があります。

> :{ 
> 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 ()

これは、インデントが変更される可能性のあるファイルから定義を貼り付ける場合にのみ重要です。

53
Justin Bailey

:{および:}はかなり新しい機能です。 GHCをアップグレードする必要がある場合があります。

編集:確認済み、 http://www.haskell.org/ghc/docs/6.8.2/html/users_guide/release-6-8-2.html を参照

17
Dan

:{および:}だけのためにGHCをアップグレードしたくない場合は、すべてを1行で記述する必要があります。

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

mustが複数行に書かれているというHaskellの単一の定義を知りません。上記は実際にGHCiで機能します:

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

doブロックなどの他の式では、中括弧とセミコロン(エフ)を使用した非レイアウト構文を使用する必要があります。

7
C. A. McCann