2012-10-11 2 views
1

문자열 목록을 사용하여 첫 번째 두 문자열을 포함하는 목록을 결과의 튜플로 반환하는 Haskell 함수를 작성했습니다. 그래서 예를 들어 출력은 다음과 같습니다목록의 첫 번째 두 문자열을 튜플로 포함하는 목록 반환

listtuple ["bride", "zilla", "crazy", "women"] = [("bride", "villa")] 
listtuple ["basketball", "football"] = [("basketball", "football")] 

내가 지금처럼 접근의 생각 방법 :

listtuple :: Eq a => [Str a] -> [(Str a, Str a)] 
listtuple xs = [(x,y) | x <- xs !! 0, y <- xs !! 1] 

는 기본적으로 난 그냥 단지의 제 1 및 제 2 인덱스의 요소를 선택할 수 있다는 생각을 목록하지만 오류가 발생했습니다. 도움이 필요 하신가요?

답변

7

이 있었다. 그 이유는 당신이 쓴 지능형리스트는 다음으로 변환한다는 것입니다 :

do x <- xs !! 0 -- Treat the first element of xs as a list 
    y <- xs !! 1 -- Treat the second element of xs as a list 
    return (x, y) 

이이 문제를 보여 그들이 나열하지 않을 때 당신은 목록으로 xs !! 0xs !! 1을 치료하고 있습니다.xs !! 0는 단지 하나의 요소이다, 그래서 당신은 xxs !! 0 같다는 것을 선언 할 경우, 당신은 사용

let x = xs !! 0 
in <some expression that uses x> 

<- 목록에 이해 구문이 같은 일을하지 않고 당신이 목록 놀지 추천 컴파일러가리스트 comprehension을리스트 모나드로 변환하기 때문에리스트 모나드가 어떻게 작동하는지 이해할 때까지

이제 두 번째 문제는 (!!)을 사용한다는 것입니다. (!!)과 같은 부분 기능을 명확하게 처리하고 패턴 일치를 사용하여 이러한 문제를 해결하는 데 집중해야합니다. 숙어 방법은 처음 두 요소에 패턴 일치하는 것입니다 요청하는 일을합니다 : 것을 제외하고

listtuple (x:y:_) = (x, y) 

... 미만이 개 요소를 포함 목록에 실패합니다. 당신은 Just 성공적인 결과를 감싸는 Maybe로 결과를 저장하여이를 방지하고, Nothing 실패 나타냅니다

listtuple :: [a] -> Maybe (a, a) 
listtuple (x:y:_) = Just (x, y) 
listtuple _  = Nothing 
1

내가 볼 수있는 코드에는 몇 가지 오류가 있지만, 코드가 작동하지 않는 이유에 대해 구체적인 질문이 있으면 알려 주시기 바랍니다.

먼저 제공 한 유형 서명이 유효하지 않습니다. String은 매개 변수가없는 데이터 구조입니다. 물론 Str이라는 데이터 구조를 정의하지 않는 한 Str a은 아무 것도 아닙니다. String의 목록에는 컴파일러가 이미 StringEq의 인스턴스라는 것을 알고 있으므로 사용자가 제공 한 동일성 제약 조건이 필요하지 않습니다.

둘째, Where 절의 위치와 모양이 같은 목록 이해 구문을 사용하고 있습니다. 하스켈은 x 요소를 바인딩하기 전에 xs !! 0을 평가하려고 시도한다고 생각하십시오. 이것은 목록 이해이기 때문에 xsString (실제로는 Char의 목록)의 목록이기 때문에 즉시 실패하지 않을 수도 있지만 x30 내의 첫 번째 및 두 번째 문자열에서 가져온 Char의 튜플로 끝납니다.

원하는 패턴을 만들어내는 간단한 방법이 있습니다. 이것은 전체 기능 아니라고

listtuple :: [a] -> [(a, a)] 
listtuple (x:y:zs) = [(x, y)] 

주 (당신이 그것을 두 개 미만 요소 목록을 전달하는 경우 즉, 그것은 오류가 발생합니다). 비어 있거나 하나의 요소 목록이 전달 될 때 비어있는 목록을 반환하면 합계가 될 수 있습니다. 의도 한대로 작동합니까?

다음은 자신의 버전을 작성하는 데 사용했던 정신 모형에 맞는 대체 버전입니다. 목록은 항상 하나 개의 항목 또는 없음을 포함하기 때문에

listtuple xs = [(x, y)] 
      where 
       x = xs !! 0 
       y = xs !! 1 
10

간단한 대답은

listtuple :: [a] -> [(a,a)] 
listtuple (x:y:_) = [(x,y)] 
listtuple _ = [] 

것, 그래서 Maybe을 정확하게 서버 이러한 목적을 사용하는 것이 좋습니다. 이것은 당신이 쓴 것과 같은 일이 아님을

listtuple xs = 
    let x = xs !! 0 
     y = xs !! 1 
    in (x, y) 

참고 : 당신은 아마하고 싶어 무엇

listtuple2 :: [a] -> Maybe (a,a) 
listtuple2 (x:y:_) = Just (x,y) 
listtuple2 _ = Nothing 
관련 문제