2

Haskellについて簡単な質問があります。私はLearnYoua Haskellをフォローしてきましたが、すべての辺が10以下で、三角形の辺の長さを計算するために使用される次のスニペットの実行順序/ロジックについて少し混乱しています。三角形の全周は24です:

[(a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c==24]

b私を混乱させる部分は、とaバインディングの上限拡張です。私が収集したものから、..c..bは、同じ三角形の辺のセットの追加の順列(組み合わせ?)を削除するために使用されます。

で実行すると..c/b、答えが得られます。

[(6,8,10)]

私が持っていないとき..c/b

[(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2, a+b+c==24]

最初に入力したときは入力しなかったので、次のようになりました。

[(8,6,10),(6,8,10)]

これは明らかに同じ三角形を表していますがab値が入れ替わっています。

それで、誰かがここで何が起こっているのかについての論理/実行/評価を私に教えてもらえますか?

4

3 に答える 3

7

元のバージョンでは、すべてのトリプレット (a、b、c) が考慮されます。ここで、c は 1 から 10 までの数値、b は 1 から c までの数値、a は 1 から b までの数値です。(6,8,10) はその基準に適合しますが、(8,6,10) は適合しません (ここでは a が 8 で b が 6 であるため、a は 0 と 6 の間にありません)。

あなたのバージョンでは、a、b、c が 1 から 10 の間にあるすべてのトリプレット (a、b、c) を考慮します。その中のすべての数値が実際に 1 から 10 の間であるため、除外されません。

命令型 for ループの観点から考えると、バージョンは次のようになります。

for c from 1 to 10:
  for b from 1 to 10:
    for a from 1 to 10:
      if a^2 + b^2 == c^2 and a+b+c==24:
        add (a,b,c) to the result

元のバージョンはこれを行いますが:

for c from 1 to 10:
  for b from 1 to c:
    for c from 1 to b:
      if a^2 + b^2 == c^2 and a+b+c==24:
        add (a,b,c) to the result
于 2012-06-08T14:12:45.513 に答える
1

concatMapリスト内包表記は、バインディングの範囲を明確にするなどの他の関数の観点から記述できます。ワンライナーとして、あなたの例は次のようになります。

concatMap (\c -> concatMap (\b -> concatMap (\a -> if a^2 + b^2 == c^2 then (if a+b+c == 24 then [(a,b,c)] else []) else []) (enumFromTo 1 b)) (enumFromTo 1 c)) (enumFromTo 1 10)

ええ、それは醜いように見えますが、それはHaskellがあなたの理解を脱糖するものに似ています。各変数、、およびのスコープは、aこれからb明らかcです。

Listまたは、これはモナドで書くことができます:

import Control.Monad

example = do c <- [1..10]
             b <- [1..c]
             a <- [1..b]
             guard (a^2 + b^2 == c^2)
             guard (a+b+c == 24)
             return (a,b,c)

Listこれは、モナドとguard:の定義を考えると、実際には上記のワンライナーと非常によく似ています。

instance Monad [] where
    return x = [x]
    xs >>= f = concatMap f xs

instance MonadPlus [] where
    mzero = []
    mconcat = (++)

guard bool = if bool then return () else mzero
于 2012-06-08T18:00:14.573 に答える
1

実行順序についてではありません。最初の例では、縮退したソリューションは表示されません

[(8,6,10)]

以来a <= b <= c。2番目のケースa > bでは、リスト内包表記に含まれています。

于 2012-06-08T14:11:18.320 に答える