2014-01-18 3 views
3

나는 readFile 함수에 간단한 처리기를 추가하려고 해요 : 따라서 readHandler :: IOError -> IO()예외 'ReadFile을'

Couldn't match type `()' with `[Char]' 
Expected type: IOError -> IO String 
    Actual type: IOError -> IO() 
In the second argument of `catch', namely `readHandler' 
In a stmt of a 'do' block: 
    contents <- (readFile "path") `catch` readHandler 
In the expression: 
    do { contents <- (readFile "path") `catch` readHandler; 
     putStrLn contents } 

:이 컴파일 할 때

readHandler :: IOError -> IO() 
readHandler e 
    | isDoesNotExistError e = putStrLn "The file does not exist" 
    | otherwise = putStrLn "Something went wrong" 

main = do 
    // stop executing if there is no file 
    contents <- (readFile "path.xml") `catch` readHandler 
    // generates [(x,y),(x,y)] 
    coordinates = parseXML contents 
    // I want to do something with the coordinates 
    nextFunction coordinates 

내가 오류 readHandler :: IOError -> IO String이어야합니다.

하지만이 방법으로 오류 메시지를 인쇄 할 수 없습니다.

는이 문제를 어떻게 해결해야합니까?

답변

5

catch (readFile "path") readHandler의 유형은 무엇이되어야합니까?

파일이있는 경우 분명히 String이어야하고 catch은 형식을 변경해서는 안되므로 어떤 식 으로든 String을 생성해야합니다. 예외가 발생하면 readHandler이 실행되므로 문자열도 생성되어야합니다. 이 방법 catch에서

우리가 파일에서 오지 않았다 어떤 임의의 String 우리의 기능을 계속 실행하지 않으 때문에, 이상적 미만의 매우 정교한 if 표현 :)처럼 행동한다.

대신 우리는 지금 우리가 사소한 IO() 생산해야하기 때문에

main = handle readHandler $ do 
    ... 

처럼 뭔가를 할 수 있습니다.

이 어떤 이유로 당신의 배를 떠하지 않는 경우, 또 다른 제정신 선택이 더 즐거운 Either

main = do 
    strOrExc <- try $ readFile "foo" 
    case strOrExc of 
    Left except -> print except 
    Right contents -> putStrLn contents 

물론이 Exception e => Either e a을 처리 할 수있는 무엇이든의 방법 제공으로 그 자극 예외를 변환하는 것 너 행복이야.

물론 최종 대안이 있습니다. 전체 프로그램을 바로 그곳에서 멈출 수 있습니다. 우리는 단지 readHandler

import System.Exit 

readHandler :: IOError -> IO a 
readHandler = putStrLn "Buckle your seatbelts" >> exitFailure 
+0

내가 더 명확하게 코드를 편집했습니다. 내 처리기로 두 번째 솔루션을 사용하고 파일이 발견되면 실행 체인을 계속 수행 할 수 있습니까? –

+0

@ Gert-Jan 물론, 문자열을 출력하는 대신에, 그 경우 분기를위한 문자열을 사용하고자하는 것을 넣으십시오. 이것은 물론 추한 것입니다. 불합리한 접근법은 '모세'모나드입니다. – jozefg

+0

이제 문제는 'strOrExc'이 'String'대신 'aither a0 String'유형입니다.나는 하스켈에 대한 나의 지식이 아직이 문제를 해결하기에 충분하지 않다고 생각한다. 힘든 도움에 감사드립니다! :) –

2

캐치을 변경하여이 작업을 수행 할 수있는 것은 입력이

catch :: Exception e => IO a -> (e -> IO a) -> IO a 

그래서 캐치의 첫 번째 매개 변수는 IO String, 다음 두 번째 인수 (함수 인) 것을 반환하는 경우 어느 한 쪽. 당신은 너무처럼 readHandler을 변경할 수 있습니다 :

readHandler :: IOError -> IO String 
readHandler e 
    | isDoesNotExistError e = do putStrLn "The file does not exist" ; return "" 
    | otherwise = do putStrLn "Something went wrong" ; return "" 

하지만 그 (빈 문자열을 반환)을 원하는 "부작용"인지, 확실하지 않다.

+0

이 방법이 효과적이지만 프로그램을 중지하고 빈 문자열을 반환하지 않아야합니다. 내 생각에는 더 나은 방법이 있어야합니다. –

관련 문제