2009-10-17 4 views
4

어떻게하면 haskell에 여러 문장이 있습니까?하스켈에서 다중 명령문

다음은 내가하려는 일입니다. [a, b, c, d]와 같은 목록이 있으면 다른 모든 요소를 ​​반환하므로 [a, c]가됩니다. 나는 해결책을 볼 수 있고, 내가 지금까지 가지고있는 것은 여기있다 :

fact (xs) | length(xs) `mod` 2 == 1 = head(xs) 
    | otherwise = fact(tail(xs)) 

이것은 처음에는 잘 돌아갔다가 종료된다. 내가 말할 수 있기를 원하는 것은 머리를 돌려 놓은 다음 사실 (꼬리 (xs))을 호출하는 것입니다. 어떻게해야합니까?

+2

기타 문제를 대답했다. 인덱스 카운트 다운 보조 기능에 유용한 매개 변수가 될 수 있습니다, 그래서 더 일반적인 지점을 만들 수 있습니다. 당신은 명령 적 생각 : 먼저 목록의 길이를 찾은 다음 홀수 인 경우 첫 번째 요소를 가져온 다음 함수를 호출하여 나머지 요소를 가져옵니다. 목록을 만든 다음 요소를 앞에 놓습니다. 당신이해야 할 일은 표현과 방정식의 관점에서 생각하는 것입니다.원하는 결과는 목록의 첫 번째 항목 다음에 꼬리의 꼬리에 사실을 적용한 결과입니다. 그것을 하스켈로 번역하십시오. –

답변

15

지정한 함수는 단일 요소 만 반환합니다. 당신은이 같은 thinkos을 파악하는 데 도움 유형 서명을 작성하는 것이 도움이 될 수있는

fact [] = [] -- can't call tail on a list of length 0! 
fact (xs) | length(xs) `mod` 2 == 1 = head(xs) : fact(tail(xs)) 
      | otherwise = fact(tail(xs)) 

: 당신은 같은 뭔가를 변경해야 할 것

fact :: [a] -> [a] -- convert a list of anything to another (shorter) list 

그러나 이것은 매우 느립니다 있습니다 - O (n^2)는 각 단계마다 길이가 있기 때문에 사실입니다. 훨씬 더 많은 솔루션은 한 번에 두 요소를 처리하기 위해 패턴 매칭을 사용합니다 :

fact :: [a] -> [a] 
-- Take the first element of each two-element pair... 
fact (x:_:xs) = x:fact xs 
-- If we have only one element left, we had an odd-length list. 
-- So grab the last element too. 
fact [x]  = [x] 
-- Return nothing if we have an empty list 
fact _  = [] 
14

하스켈에는 진술이 없습니다.

하스켈에서 괄호를 남용해서는 안됩니다. 오히려 언어에 익숙해 져야합니다. 그래서 원래의 코드가 bdonlan 노트로

fact xs | length xs `mod` 2 == 1 = head xs 
     | otherwise    = fact (tail xs) 

과 같아야합니다, 당신이 찾고있는 기능은 우리가 목록 [a, b, c, d]이 정말

fact []  = [] 
fact [x]  = [x] 
fact (x:_:xs) = x : fact xs 

한다고 가정합니다. 함수를 적용하고 결과를 완전히 평가합시다. 대표 목록의 두 가지 방법이 컴파일러에 의해 의미로 해석되기 때문에 [a, b, c, d]a : b : c : d : [] 정확히 동일 함을

fact [a, b, c, d] = a : fact [c, d] 
        = a : c : fact [] 
        = a : c : [] 
        = [a, c] 

참고. 세마포어 스와핑

+1

목록의 두 번째 요소를 추출하는'fact (x : _ : xs)'코드 스 니펫에서'_'의 밑줄을 그냥 쓴 단어입니다. 어쨌든 튕겨 나갈 것이므로, 두 번째 요소에는 쓸모없는 변수 이름을 할당하는 것은 어리석은 일입니다. 밑줄은 하스켈이 변수 이름을 지정하는 것을 괴롭 히지 않고 두 번째 요소를 선택하는 방법입니다. 내 의견으로는 코드를 아주 읽기 쉽게 만듭니다. – Zaid

+4

"길이"솔루션을 사용하지 않는 또 다른 이유가 있다고 생각합니다. 뿐만 아니라 효율성. 지정한 작업은 무한 목록에도 의미가 있습니다. 무한리스트 작업은 하스켈의 게으른 속성이 무한리스트 작업이 정당화 될 수있는 접근법을 제공 할 수 있기 때문에 단순한 정교 만이 아닙니다. "길이"를 사용하는 솔루션은 유한 목록에만 적용되는 반면, "게으른"방법은 무한 목록과 유한 목록 모두에서 작동합니다. OFF : 때때로, 게으른 평가는 매우 강력하고 직관적이지 않은 접근 방식을 제공 할 수 있습니다 (예 : '마법'). 순환 프로그래밍, repmin 문제. – physis

3

사실, 우리는 다음의 두 가지 패턴을 수행 할 수

  • [1,2,3,4, ...]가된다 [1,3,5,7 ...]
  • [1,2,3,4 ..]는 모두 동일한 작업을 수행

] ... 2,4,6,8 [된다, 그러나 그들은 "계산을 시작" 반대로. 같은 기능으로 두 가지를 구현합시다! 물론이 함수는 "패턴"에 따라 매개 변수화되어야합니다. 가능한 두 가지 패턴이 존재하므로 매개 변수화를위한 유형에 대해 부울이 필요합니다. 구현 : "세마포어"우리가 "플래그"로 부울 매개 변수를 사용하자 : 우리는 "플래그/세마포어를"부기, 보조 기능을 사용한

module Alternation where 

every_second :: [a] -> [a] 
every_second = every_second_at False 

every_second_at :: Bool -> [a] -> [a] 
every_second_at _ [] = [] 
every_second_at True (x : xs) = x : every_second_at False xs 
every_second_at False (x : xs) =  every_second_at True xs 

: 그것은 적절하게 교환합니다. 실제로이 보조 기능은 원래 작업의 일반화로 간주 될 수 있습니다. 제 생각에 그것은 "worker wrapper"기능입니다.

인덱스가있는 카운트 다운

작업을 더 일반화 할 수 있습니다. "modulus"m으로 매개 변수화 할 수있는 훨씬 더 일반적인 함수를 작성하지 말고 모두 m번째 개의 요소를 "수확"합니다.

  • every_mth 1 [1,2,3,4, ...] 수율 [1,2,3,4 ...]
  • every_mth 2 1,2,3,4 .. .] 수율 [1,3,5 ...]
  • every_mth 3 [1,2,3,4, ...] 수율 [1,4,7 ...]

우리가 할 이전과 같은 아이디어를 사용하십시오. 더 복잡한 "세마포어"를 사용해야합니다 : 부울 대신 자연수. 이것은 "카운트 다운"매개 변수 인덱스입니다 나는 그것이 우리의 차례입니다 부기 :

module Cycle where 

import Nat (Nat) 

every_mth :: Nat -> [a] -> [a] 
every_mth 0   = undefined 
every_mth m @ (i + 1) = every_mth_at m i 

우리는 보조 기능 ( worker wrapper)를 사용, 카운트 다운 인덱스 내가 부기 :

every_mth_at :: Nat -> Nat -> [a] -> [a] 
every_mth_at _  _ []  = [] 
every_mth_at m 0  (x : xs) = x : every_mth m xs 
every_nth_at m (i + 1) (x : xs) =  every_mth_at m i xs 

간단히하기 위해 자연수 형식은 단순한 별칭으로 여기에 "구현"되어 있습니다.

아마, 다수의 이론적 의미에서, 또한 사용자가 지정한 작업에 정확히 일치하지 청소기 대안 접근 방식이 있지만, 조정은 간단 것 같다 :

  • every_mth 1 [0,1,2,3,4,...] 수율 [0,1,2,3,4,...]
  • every_mth 2 [0,1,2,3,4,...] 수율 [0,2,4,6,8...]
  • 을하자,
  • every_mth 3 [0,1,2,3,4,...] 그것은 "우연히"는 LIS를 제공해야합니다 있도록이 여기에 지정된 따라서 [0,3,6,9...]

를 얻을 수 있습니다 모든 자연수의 지연 목록에 적용될 때 매개 변수의 배수 t.

구현시 숫자를 "0부터 시작하는"색인으로 사용하는 것이 좋습니다. 대신에 "모든 m번째", 우리는 말할 "레인 징의 인덱스로 I를 사용하여 0, 1, ..., UU 상한을 나타내고 m -1 = , 가능한 지표.이 상단 지수는

module Multiple where 

import Nat (Nat) 

every_mth :: Nat -> [a] -> [a] 
every_mth 0 = undefined 
every_mth (u + 1) = countdown u 

countdown :: Nat -> [a] -> [a] 
countdown = countdown_at 0 

countdown_at :: Nat -> Nat -> [a] -> [a] 
countdown_at _  _ []  = [] 
countdown_at 0  u (x : xs) = x : countdown_at u u xs 
countdown_at (i + 1) u (x : xs) =  countdown_at i u xs