2017-09-19 8 views
1
fac n = if n < 2 then 1 else n * fac (n-1) 

main = do 

    putStrLn "Enter a number: " 
    number <- getLine 
    print $ number >>= fac 

if文なしで再帰的階乗関数を書く方法はわかりません。私たちの教授はラムダ計算について何か言っていました。if then else文なしでhaskellの再帰的階乗関数を書く方法

+2

https://en.wikibooks.org/wiki/Haskell/Pattern_matching – Ryan

+0

[頬回答に舌(https://www.willamette.edu/~fruehr/haskell/ – gallais

答えて

5

パターンマッチングとガードは、特に単純な2つの方法です。ガードは基本的にif-then-elseの別の構文です。

fac n | n < 2  = 1 
     | otherwise = n * fac (n-1) 

if-then-elseとは異なり、これらはきちんと複数の条件をサポートしています。たとえば、

fac n | n < 0 = error "nah" 
     | n == 0 = 1 
     | n == 1 = 1 
     | n > 1 = n * fac (n-1) 

と書くこともできます。これは、if-then-else形式ではあまり見た目には見えません。パターンマッチングで

は、一方は通常、複数の定義式記述します特定の数字について

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

が、これはまた、本質的に、AN IF-THEN-ELSEにdesugars。しかしコンパイラの統合が少ないデータ型の場合は、if-then-elseでエミュレートすることができず、しばしば非常に自然に見えるコードにつながることもあります。

もう一つの非常に良いアプローチは、あなたの再帰を既存のPrelude関数にプッシュすることです。実際に反復パターンを見つけることができればするほど、同じループを何度も何度もやり直すことで回避できるバグが増えます。この1のために、あなたはproductと特別な列挙の構文を使用する場合があります:

fac n = product [1..n] 

より高度な(と大幅に悪化)技術は、数の新しい種類を定義することです。例えば教会の数字は、数字の生産者が再帰を推進することを可能にし、消費者(ここではfac)は基本ケースを提供するだけです。このスタイルでは、このような表示される場合があります。

fac n = fst (n (1,1) (\(prod, sum) -> (prod*sum, sum+1))) 

を(しかし、これは数の非常に特別なものを必要とすることにも注意してください - 確かにfacのタイプはIntまたはIntegerを受け入れることができる機能の一つではありません!)この冗談は、The Evolution of a Haskell Programmerの論理的で恐ろしい結論に導かれます。

+0

'Bool'の'(==) 'からパターンマッチングを忘れることはありません。これはガードとif/then/elseの両方が砂糖になるものです(Haskellは扱う方法があまりにも多すぎるかもしれませんブール) – Carl

1

もし/ then/elseとguardは実際にはパターンマッチングのための文法的な砂糖です。同様に

case b of 
    True -> c 
    False -> d 

if b 
    then c 
    else d 

desugars、

f x 
    | b = c 
    | d = e 
f x = g 

desugars

f x = case b of 
     True -> c 
     False -> case d of 
      True -> e 
      False = g 

にあなたは常に直接caseを使用することができます。しかし、あなたは手で行うことができる非常に単純な最適化があります。

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

使用末尾再帰:あなたはpはコンストラクタとリテラルで作られて

case x == p of 
    True -> a 
    False -> b 

が表示された場合、あなたはこれを試す

case x of 
    p -> a 
    _ -> b 
1

で全体を置き換えることができます。

factorial n = f n 1 

f 0 acc = acc 
f n acc = f (n-1) (acc*n) 

main = print $ factorial 5 

出力:

120