2013-06-29 3 views
17

방금 ​​하스켈을 사용하기 시작했고, 주어진리스트가 두 번째 원소가 두배로 된리스트를 반환하는 함수를 작성하려고했습니다. 지금까지이 함께 왔어요하스켈 : 목록의 두 번째 원소를 두 번씩 두번 씩

:

작동하지만 난 너희들이 그 함수를 작성합니다 궁금 해서요
double_2nd :: [Int] -> [Int] 
double_2nd [] = [] 
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs) 

. 좀 더 보편적 인 방법이 있습니까?

+0

위의 코드는 목록에 단일 요소가 들어있는 경우가 부족하다고 생각합니다. '[] = []'뒤에 – Pejvan

답변

42

나쁘지 않은데, 수정 사항을 제안했습니다. 일단 기본 라이브러리에 익숙해지면 더 높은 수준의 함수를 사용하여 명시 적으로 재귀를 피할 수 있습니다. 예를 들어 다른 모든 함수가 *2 인 함수 목록을 만들고 해당 함수 목록을 (zip)에 적용 할 수 있습니다. 당신의 번호 목록 : 강령술의

double = zipWith ($) (cycle [id,(*2)]) 
+1

훌륭하게 조명. –

+1

목록 이해 :'double lst = [f x | – Ankur

+6

@Ankur 튜플의 생성과 소멸을 피할 수 있기 때문에 필히 병렬리스트 이해력을 읽는 것이 더 깔끔합니다. 'double lst = [f x | x <- lst | –

4

은 홀수 길이의 목록을보십시오 :

Prelude> double_2nd [1] 
[1,*** Exception: Prelude.head: empty list 

그리고 당신은 당신의 코드로 문제를 볼 수 있습니다. '머리'와 '꼬리'는 결코 좋은 생각이 아닙니다.

+0

Mhm과 일치하는'double_2nd [x] = [x]'를 추가 할 것입니다. 홀수 길이리스트를 사용하는 방법에 대한 아이디어가 있습니까? – user2036087

18

일부 스마트 패턴 일치로 "빈 목록"예외를 피할 수 있습니다.

double2nd (x:y:xs) = x : 2 * y : double2nd xs 
double2nd a = a 

이 너무 xs 먼저 패턴 x:y:xs 대해 일치한다, 다음

double2nd xs = case xs of 
    x:y:xs -> x : 2 * y : double2nd xs 
    a -> a 

패턴 매칭하기위한 수행 단순히 구 당이다. 그런 다음 실패하면 캐치 올 패턴 a이 성공합니다.

+0

멋지다! 호기심처럼 (불행히도 하스켈에 있지는 않겠습니다.) 패턴 매치 처가 첫 번째 패턴과 일치하는 목록에 대해서도 두 번째'duble2nd'를 선택하지 못하게하는 것은 무엇입니까? 주문이되었거나 복잡한 작업이 있습니까? – mariosangiorgio

+3

@mariosangiorgio : 패턴 일치를위한 표준 해석은 "위에서 아래로, 왼쪽에서 오른쪽으로"입니다. 표준 해석이하는 것과 같은 선택을하는 한, 순서를 바꿀 수 있습니다. –

+0

@Rhymoid 답장을 보내 주셔서 감사합니다! "왼쪽에서 오른쪽으로"무엇을 의미하는지 명확하게 설명해 주시겠습니까? – mariosangiorgio

9

조금,하지만이 방법은 저를 위해 아주 잘했다라고 생각하고 공유하려는 :

double2nd n = zipWith (*) n (cycle [1,2]) 

zipWith 함수를 취하고 그 적용 두 목록 (첫 번째 항목부터 첫 번째 항목, 두 번째 항목에서 두 번째 항목까지 등)의 일치하는 항목 전반에 걸쳐 기능을 수행합니다. 함수는 곱셈이며, 압축 된 목록은 1과 2의 끝없는 순환입니다. zipWith (및 모든 우편 번호 변형)는 더 짧은 목록의 끝에 멈 춥니 다.

+3

양면에서 'n'을 제거하면이 값을 줄일 수 있습니다. 즉, double2nd = zipWith (*) (순환 [1,2]) – DNA

+0

입력 목록은 어디로 이동합니까? [zip은 세 가지 인자가 필요합니다] (http://zvon.org/other/haskell/Outputprelude/zipWith_f.html); n을 떨어 뜨리면 뭘 기대하니? – steegness

+3

시도해보십시오! 우리는'zipWith'에 처음 두 개의 인수를 제공합니다 (즉, 부분적으로 적용합니다). 이것은 마지막 인수를 여전히 기대하는 함수를 만듭니다. 그런 다음이 함수의 이름을 double2nd로 지정하면 완료됩니다. 이 경우 인수를 명명 할 필요가 없습니다. 이러한 단순화를 η 감소라고합니다. 우리가 제거하는 논증은 마지막 것이어야합니다. 그러나이 경우 n과 순환을 바꿀 수 있습니다. 왜냐하면 우리가 곱셈을하기 때문에 순서가 중요하지 않기 때문입니다. – DNA

관련 문제