2016-12-06 1 views
0

사람의 성을 사용하고 성만 반환하는 하스켈 함수를 작성하려고합니다. 예를 들어 getName "Hans Christian Anderson""Anderson"을 반환해야합니다.하스켈 오류 - 예상 유형 'Char'와 실제 유형 '[Char]'을 일치시킬 수 없습니다.

getname :: String -> String 
getname fullName = do 
    let nameList = splitOn " " fullName -- split the full name into individual names 
    let reversedName = reverse nameList -- reverse the full name 
    let lastName = reversedName !! 0  -- get the first name from the reversed list 
    return lastName 

하지만이를 컴파일하려고 할 때마다, 나는 다음과 같은 오류 얻을 :이 기능은 다음과 같습니다

Couldn't match expected type ‘Char’ with actual type ‘[Char]’ 
In the first argument of ‘return’, namely ‘lastName’ 
In a stmt of a 'do' block: return lastName 

나는 완전히이 오류를 이해 모르겠어요합니다. 내가 하스켈을 이해함에 따라 구조가 [Char]String과 같을 것이다. 왜 그냥이 Char 형식이 반환 문에서 문자열로 나타나는 것으로 예상하는지 이해가 가지 않습니다. 나는 각 라인을 넘었고 그들은 나에게 맞는 것 같다.

이 문제가 발생하는 이유와 해결 방법에 대한 조언이 있으면 감사하겠습니다.

+1

이 좋은 프로그래밍 연습이다. 그러나 [이름에 관한이 이야기를 즐기실 수도 있습니다.] (https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/). –

+0

@DanielWagner 이전에 그런 것을 보았습니다. 실제로 잘못된 결과가 나오지 않도록 내가 다루고있는 이름에 대해 얼마나 조심해야하는지 조심했습니다. 그러나,이 연습의 목적을 위해, 나는 약간 무거워서 많은 가정들을 생각해 볼 수있었습니다. –

답변

5

do 표기법을 사용하지 마십시오. 함수의 반환 값이 [Char]이므로 return의 인수는 Char 값이 될 것으로 예상됩니다 (return :: a -> [a]).

do 표기법을 필요로하는 여기서는 아무 것도하지 않습니다. 그냥 일반 함수 호출을 사용하십시오.

getname fullName = (reverse (splitOn " " fullName)) !! 0 
+0

return이 왜 이와 같이 작동하는지 완전히 이해할 수 있는지 확신 할 수 없지만 코딩 배경에 따라 기능적 컨텍스트에서 생각하지 않기 때문에 생각합니다. 'do ... return ... '을 사용하면 정규 함수 호출을 사용했을 때와 다른 결과를 얻을 수 있다는 것을 알지 못했지만 더 자세한 문서를 살펴볼 것입니다. 귀하의 회신에 감사드립니다! –

+2

이것이'return'의 목적입니다. 그것의 일반적인 타입은'return :: Monad m => a -> m a'이지만, 여기서'm'은'getname'의 선언 된 반환 값 때문에'[]'로 고정됩니다. 'return' 함수는 대부분의 프로그래밍 언어에서 같은 이름의 문장과 아무 것도 같지 않습니다. – chepner

+0

그래, 그렇게 보일지 모르겠군요.나는 그것이 항상 행동하는 것을 찾은 것처럼 행동하는 것을 기대했습니다. –

2

비 결정적 계산을 설명하는 것처럼 의도 한 코드가 실수로 목록 모나드에서 작동합니다. 그 모나드 나 다른 모나드는 필요 없습니다. 따라서 이것을 위해 do을 사용하지 마십시오. 당신이 원한다면 당신은 여전히 ​​let .. in ..를 사용할 수 있습니다 또는

getname :: String -> String 
getname fullName = 
    let nameList = splitOn " " fullName -- split the full name into individual names 
     reversedName = reverse nameList -- reverse the full name 
     lastName = reversedName !! 0  -- get the first name from the reversed list 
    in lastName 

last 사용

getname :: String -> String 
getname fullName = last (splitOn " " fullName) 

last이 부분입니다주의 : 입력 문자열에 이름이없는 것처럼 즉시 프로그램을 충돌합니다 . 더 안전한 방법이 될 수있다 :

getname :: String -> Maybe String 
getname fullName = case splitOn " " fullName of 
    [] -> Nothing 
    xs -> Just (last xs) 

심지어 :

getname :: String -> Maybe String 
getname fullName = safeLast (splitOn " " fullName) 

-- This should be already there in the library, IMO 
safeLast :: [a] -> Maybe a 
safeLast []  = Nothing 
safeLast [x] = Just x 
safeLast (_:xs) = safeLast xs 
+0

응답 해 주셔서 감사합니다. safeLast와 관련하여 실제로 하스켈 커뮤니티에 제안해야합니다. 그렇지 않으면, 나는 그들이 hackage에 관해서 모든 것을 허락한다고 생각합니다! –

관련 문제