2017-12-18 10 views
2

지도에서 '머리'기능을 사용하고 싶습니다. 'head'함수는 비어 있지 않은 목록 만 허용합니다. 나는 내가 한 번 목록의 목록을 반복하거나 "만약 조건"을 넣을 수 있는지 궁금 두 번빈 목록 문제에 대한 헤드 기능

let listOne = filter(\x -> if length x > 0) ll 
map(\x -> head x) listOne 

을 목록의 목록을 반복 할 필요가

let ll =[["dog", "cat"], ["pig", "cow"], []] 

: 나는리스트의 목록을 가지고 '필터'가없는지도 내부

모든 의견을 환영합니다.

+1

빈 목록에 대해 원하는 것은 무엇입니까? 그냥 필터링/무시합니까? 왜 필터가 원하는 것을하지 않습니까? – puhlen

+0

필터는 빈 목록 만 제거하지만 'head'를 사용하고 head 요소에 대해 작업을 수행하려고합니다. –

+0

그러나 빈 목록에는 머리가 없습니다. 지도 + 필터가하지 않는 것은 무엇입니까? 목록을 두 번 반복하는 것에 관심이있는 경우에만 그렇지 않습니다.이러한 작업은 지연 평가됩니다. – puhlen

답변

8

예, 당신은 목록 이해 문으로 작성하고, 대신 일치 패턴을 사용할 수있는 사실 :

result = [ h | (h:_) <- ll ] 

또는 함수로 :

heads :: [[a]] -> [a] 
heads ll = [ h | (h:_) <- ll ] 

그래서 여기에 우리 비어 있지 않은 모든 목록과 일치하는 패턴 (h:_)을 사용하고 우리는 직접 그러한 목록의 머리 h을 얻은 다음 목록에 추가합니다. 목록 이해 (왼쪽 화살표 <-의 왼쪽에있는 패턴을 사용하면 패턴과 일치하지 않는 요소는 건너 뜁니다). 당신이 무한 목록 작업하는 경우 length가 무한 루프에 집착하기 때문에

이 또한 length를 사용하는 것보다더 안전합니다. 또한 비 합계 head 함수에 대한 패턴을 사용하면 구문이으로 보장되어이 함수가 작동한다는 것을 보증합니다 (예, 비어 있지 않은 요소가 필터링되면, 우리는 물론 head이 오류를 일으키지 않을 것이라고 확신합니다. 우리는 head 함수에 대한 정보를 가지고 있기 때문에 이것을 알고 있습니다.)

if을 사용 했으므로 thenelse 부분을 사용하지 않으려 고 시도하면 구문 오류가 발생합니다. 또한

, 우리는 @DanielWagner 말한다처럼 사용 예를 들어, 다르게 heads 함수를 작성 할 수 있습니다

heads :: [[a]] -> [a] 
heads ll = concatMap (take 1) ll 

나에 의해을 목록 모나드의 바인드 사용 :

heads :: [[a]] -> [a] 
heads = (take 1 =<<) 

또는 우리는 2 차원 목록을 조 변경 할 수 있습니다. 이 경우 첫 번째 행에는 목록의 모든 헤드가 포함됩니다. 그러나 그러한 행이 있다고 보장 할 수는 없으므로 마지막에 빈 목록을 추가 할 수 있습니다.

heads :: [[a]] -> [a] 
heads = head . (++ [[]]) . transpose 
+2

동일한 아이디어의 또 다른 재미있는 철자 :'heads = concatMap (take 1)'. 완전히 다른 생각 :'heads = head. (++ [[]]). 전치하다. –

+0

@DanielWagner : 나는 정말로 이것을 좋아한다. 특히 첫 번째. –