2012-06-08 1 views
2

하스켈에 대해 빠른 질문이 있습니다. 나는 Learn You a 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]

저 혼동하는 ba 및 바인딩에 결합 된 상부 확장 부분이다. 내가 모은 것에서, ..c..b은 삼각형 변의 동일한 세트의 추가적인 순열 (조합?)을 제거하는 데 사용됩니다. 내가하지 않을 때처럼

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

:

[(6,8,10)]

나는 ..c/b이없는 : 나는 ..c/b 그것을 실행하면

, 나는 답을 얻을 처음에 입력했습니다.

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

ab 값을 제외하고는 동일한 삼각형을 분명히 나타내는 것은 분명히 바뀌 었습니다.

그래서 누군가 여기서 논리와 실행/평가를 통해 나를 걸을 수 있습니까?

답변

7

c는 1과 10 사이의 숫자이고, b는 1과 c 사이의 숫자이며, a는 1과 b 사이의 숫자 인 모든 쌍곡선 (a, b, c)을 고려합니다. (6,8,10)은 그 기준에 부합하며, (8,6,10)은 그렇지 않습니다 (여기서 a는 8이고 b는 6이므로 a는 0과 6 사이에 있지 않습니다).

귀하의 버전에서는 a, b 및 c가 1과 10 사이의 모든 쌍곡선 (a, b, c)을 고려합니다. a, b 및 c가 서로 어떻게 관련되는지에 대한 제한을 두지 않으므로 (8, 거기에 모든 숫자가 실제로 때문에 6, 10)이 제외되지 않은 1 사이 당신이-루프 필수적의 관점에서 생각한다면 10

, 버전이 수행합니다 그동안

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 
+0

고챠, 고마워! – Josh

1

실행 순서가 아닙니다. 첫 번째 예제에서 당신은 타락 솔루션을 a <= b <= c 이후

[(8,6,10)] 

표시되지 않습니다. 두 번째 경우에는 a > b가 목록 이해에 포함됩니다.

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) 

그래, 추한 보이지만, 하스켈로 함축을 desugars 것과 비슷합니다.변수 a, bc 각각의 범위는 여기에서 분명해야합니다.

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

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

guard bool = if bool then return() else mzero 
: 상기 List 모나드 정의와 guard 주어진

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 모나드로 기록 될 수있다

+0

나는 그 모든 것을 따랐다 고 말할 수는 없지만, 대단히 감사하다고 말 할 수 있으며, 몇 주 안에 분명히 이해할 수 있기를 바랍니다. 감사! – Josh

+0

적어도 하나의 라이너를 따라 왔습니까? 'concatMap f xs'는'f'가 항목 목록을 생성하고'concatMap'이 그것들을 추가한다는 것을 제외하면'map f xs'와 같습니다 :'map (\ n -> [1..n]) [1..3]' [1. [1], [1,2], [1,2,3]],'concatMap (\ n -> [1..n]) [1..3]은'[1,1 , 2,1,2,3]. 기본적으로 한 줄자는 [1..10], [1..c], [1..b]에 중첩 된'concatMap'을 사용하여 트리플을 생성하고'[] '를 반환하면 트리플을 거부하고' (a, b, c)]'를 사용하여 트리플을 수락합니다. 최종 결과는 좋은 트리플을위한 모든 싱글 톤'[(a, b, c)]리스트와 나쁜 것들을위한 빈리스트를 연결한다. –