2016-08-24 3 views
0

ハスケルを学んでいるとき、与えられた数のすべての整数除数を返す関数を作ろうとしています。だから、2つのネストされたwhere句を使用して作成しましたが、動作しません。 exs2.hs:49:24: Parse error in pattern: negRef/2ハスケルで入れ子になった `where`節を使う

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x/2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list 
     where 
     negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList) 
     negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList 

その後、間違ったことは何ですか:

エラーがを返さ?それはよくインデントされているようです。

+4

'negRef/2'は有効なパターンではありません。 – MathematicalOrchid

+3

内部where句は、divの定義の2行目のスコープ内にのみあります。 divsの最初の行がnegDivを呼び出すとき、内部のwhere節はスコープにありません。それとパターンのこと。 – pigworker

+0

それでは、どうすればその分割パターンを正しく書くことができますか? @MathematicalOrchid – fant0me

答えて

2

あなたの2番目のwhere -clauseは、divsスコープの名前を使用しません。あなたはそうのような1つの句を使用することができます。

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x/2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list 
    negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList) 
    negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList 

あなたが本当にネストされた句を使用して機能を表現したい場合は、あなたがlet ... inを使用することができます。

この場合、これは有用ではありません。where句を使用することをお勧めします(多くの場合、let ... inよりも好まれることがよくあります)。

negDivを使用する最初の式ではなく、divsの2番目の式にこの節を付けることが理由です。

PS:MathematicalOrchid saidのように、negRef/2は正しいパターンではありません。エラーが発生した場所です。

+0

時には、 'どこに'が 'レット'よりも好まれることもありますが、時にはそれは逆です。私は、他のものよりも熟達しているとは思わない。たとえば、http://stackoverflow.com/questions/4362328/haskell-where-vs-letを参照してください。 –

2

もう1つの問題は、/演算子が整数では機能しないということです。ハスケルでは、/はフィールドの除算演算子であり、RationalDoubleのようにFractionalタイプが必要です。

整数部門では、代わりにdiv or quotを使用してください。

+0

これまでに 'div'を使ってやったことがありますが、同じエラーが返ってきました。 – fant0me

1

あなたはいくつかの問題があります。

  1. することはできリテラルとデータ構築、/好きではない任意の関数の唯一のパターンマッチ。
  2. /は、Fractional a値の場合にのみ定義され、Integralではありません。代わりにdivを使用してください。
  3. negDivの定義には、再帰呼び出しの引数がありません。しかし、議論がどうあるべきかははっきりしない。

Aほとんどはバージョン修正:ところで

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x `div` 2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list | ref `mod` num == 0 = divs ref (num-1) (num:list) 
         | otherwise   = divs ref (num-1) list 
    -- Three arguments, but only two given to each recursive call 
    negDiv x y negList | x == negRef `div` 2 = x:y:negList 
         | x `mod` y == 0  = negDiv (y-1) (y:negList) 
         | otherwise   = negDiv (y-1) negList 

を、これははるかに簡単に

divisors' x = ds ++ (map negate ds)    -- positive and negative ds 
       where ds = filter (divs x) [1..x] -- d such that d divides x 
        x `divs` y = x `mod` y == 0 -- Does y divide x? 

あるいは

いつでも
divisors' x = [d | d <- [(-x)..x], d /= 0, x `mod` d == 0] 

で行われますおそらくあなたは正しい高次関数やリストの理解を見落としているでしょう。

関連する問題