2012-09-25 2 views
3

나는 하스켈에서 프로그래밍을하려고합니다. 파일을 읽고 라인 함수를 사용하여 파일의 모든 라인을 목록에 넣으려고합니다. 나는이 오류가 점점 계속, 그러나readFile 뒤에 행 사용

file = "muh.rtr" 
readTrack :: String -> Track 
readTrack file = 
    do  let defFile = readFile file 
      let fileLines = lines defFile 

을 : 여기에 일부 코드는

Parser.hs:22:39: 
    Couldn't match expected type `String' with actual type `IO String' 
    In the first argument of `lines', namely `defFile' 
    In the expression: lines defFile 
    In an equation for `fileLines': fileLines = lines defFile 

지금 어딘가에 몇 가지 답을 찾으려 시간 동안 인터넷을 검색 한을하지만 난 너무 운이없는 것 지금까지.

+1

[답변은] (http : // stackoverflow.com/questions/12664050/works-in-ghci-but-not-loaded/12665589 # 12665589) 나는 당신과 같은 오류 메시지를받는 사람에게주었습니다. – AndrewC

답변

6

readFile의 유형은

readFile :: FilePath -> IO String 

그래서 당신이 결과를 바인딩 <-를 사용할 필요가 있으며, 함수는 IO Track을 반환해야한다.

readTrack :: String -> IO Track 
readTrack file = 
    do defFile <- readFile file 
    let fileLines = lines defFile 
    ... 

나는 예제 Input and Output chapter of Learn You a Haskell for Great Good!에 대한 하스켈의 IO에 좋은 자습서를 읽을 것을 권 해드립니다. 이 같은

readTrack :: String -> IO Track 
readTrack file = do defFile <- readFile file 
        let fileLines = lines defFile 
        -- etc.... 

... 또는 뭔가 :

9

당신은 아마 이런 식으로 뭔가 하나 원

readTrack :: String -> IO Track 
readTrack file = do fileLines <- liftM lines (readFile file) 
        -- etc.... 

을하지만 당신이 정말로 중지되어 무엇을해야하는지에 대한 소개를 찾아 이동 Learn You a Haskell과 같은 언어를 사용하고 일부 시간을 읽으십시오.

GHC에 아주 간단한 오류만으로 구성된 피드 코드는 스택 오버플로에 오류 메시지를 게시하는 것이 좋은 방법이 아닙니다.

+0

고마워요,하지만 제가 인내심을 잃어서이 질문을 게시 한 이유는 내일 마감일이 있기 때문에 이미 저녁 늦게까지 피곤해 졌기 때문입니다. 어쨌든, "readTrack :: String -> Track"이되어야합니다 (나는 그와 같은 함수를 구현해야한다고 말하는 작은 프로젝트를 수행하고 있습니다) 다른 방법으로는 트랙과 함께 "선"을 사용할 수 없습니까? IO 트랙? – user1683526

+7

@ user1683526 나는 이런 종류의 코멘트를 보았습니다. ("나는 내일까지 만기가되어 빠른 응답이 필요합니다.") 몇 번이나, 매우 설득력을 찾지 못했습니다. 귀하의 가난한 계획은 우리의 책임이 아닙니다. 당신이 진보 할 수있는 것을 배우고 싶다면 진전을위한 기한을 가졌는지 여부와 관계없이 그것을 배우셔야합니다. –

+4

@ user1683526 : 이것이 과제 과제의 일부라면, 한 번의 마감일보다 * 더 큰 문제 *가 있습니다. 질문과 의견 모두 당신이 아주 필수적이고 기본적인 개념을 이해하지 못한다고 제안합니다. 이 속도로 코스에서 잘하지 못할 것입니다. –

5

readFile은 IO string입니다. 즉, 문자열을 반환하는 IO 계산입니다. 즉, 대신 <-을 사용해야 해당 문자열을 반환 할 수 있습니다.

readTrack file = 
    do 
     defFile <- readFile file 
     ... 

당신은 같은 라인의 반환 값으로 IO 계산,하지 않은 일을 바인딩 let를 사용할 수있는, 즉 일반 문자열입니다.

readTrack file = 
    do 
     defFile <- readFile file 
     let fileLines = lines defFile 
     ... 

마지막으로, 당신은 당신이

readTrack file = 
    do 
     defFile <- readFile file 
     let fileLines = lines defFile 
     fileLines --Doesn't actually work! 

하지만 뭔가를 시도 할 수도 있습니다 값을 반환 할 필요가 불행하게도, 우리는 "할"블록 내부에와 모나드 계산을 반환하려고하기 때문에, 기능을하지 String!

readTrack file = 
    do 
     defFile <- readFile file 
     let fileLines = lines defFile 
     return fileLines 

하는 것으로, IO [String]을 반환에서 우리가 다시 IO 모나드에 fileLines를 보낼 필요가 (기억 " return "여기에 이 아니라 대부분의 언어에서 정상적으로 발견 될 수있는 return 문과 순수한 함수에서 사용하면 안됩니다.

이 모든 것이 처음에는 많은 것처럼 보일 수 있습니다.나는 당신이 언어에 대한 더 나은 응답을 얻을 때까지 순수한 함수 (입출력/모나드가없는)를 고집 할 것을 제안한다.

4

당신은 그렇게 할 수 없어 - 당신은 IO 모나드로 실행했습니다. 문으로 IO T

readTrack :: String -> IO Track 
readTrack file = do 
    defFile <- readFile file 
    let fileLines = lines deffile 
    ... 
    return whatever 

생각해 (표현 반대) 반환 형식 T과 : 당신이해야 할 것은 같은 것입니다. 명령문에는 부작용이 있지만 표현식에는 표현식이 없기 때문에 명령문을 표현식으로 변환 할 수 없습니다. 형식 시스템이이를 강제하기 때문에 형식 서명이 작동하지 않습니다.

참고 do 블록의 다른 과제와 같은 구문은 다음 let baz = quux 구문 순수 관능 평가를 위해 사용되는 반면,이 예에서, foo <- barIO 작업에 사용된다. 이것은 모나드 입출력을 사용함으로써 더욱 악화되고 있습니다 - 하스켈의 다형성 시스템의 완전한 보편성에서 더 의미가 있지만, 순수 대 부작용 연산의 구문 적 표시기를 갖는 것이 반드시 나쁜 것은 아닙니다.

일반적으로

, 순전히 기능 영역에서 구현의 대부분을 유지하려고하는 것이 좋습니다 : 다음IO 모나드에 I/O 작업을 설명, 일반 기능적인 방법으로 순수 계산을 구현한다. IO 모나드에 루프를 작성하는 것은 일반적으로 초보자가 실수로하는 것으로 목록 작성 또는 재귀 함수로 더 적합합니다. 함수가 유형 readTrack :: String -> Track을 가정하는 경우

3

, 당신은 문자열에 파일 이름입니다 확신? 아마도 데이터 일 것입니다. 그렇다면 readFile을 사용하지 마십시오. 일부 샘플 데이터 및 테스트 것을 사용하여 쓰기 등이 숙제 파일을 사용하지 않은에 대해 SO IO. 난 당신이이기 때문에 위기에 링크하지거야, 그리고 수도에

sampleData = "2 3\n1 30 234 45\n1 2 32 4\n5 3 4 23" 

(다른 질문 어떤 경우에는 당신이 StackOverflow 검색 스킬을 향상 시키도록 강요 할 것입니다. :))

어쨌든 String을 해결하면 더 많은 점수를 얻게 될 것입니다. 문제가 IO 문제를 해결하는 것보다

지연 ReadFile을 문제는 순수 버전 작업을 가지고 때까지, 그렇지 않으면 당신은 훨씬 더 복잡 필요 이상으로 될 것이다 이는 IO 모나드에서 대부분의 코드를 작성 끝낼 수 있습니다.

당신은 순수한 기능을 소요하고 IO와 같은 다른 컴퓨팅 환경에서 작동하도록 리프트, 당신은 지금

readTrackFrom :: FilePath -> IO Track 
readTrackFrom filename = fmap readTrack (readFile filename) 

, fmap :: Functor f => (a -> b) -> f a -> f b 할 수있는, 순수한 기능 readTrack :: String -> Track 있습니다.

IOFunctor입니다. 내일 (오늘 밤이 아닌)보세요. 우리는 이것을 (String -> Track) -> IO String -> IO Track 유형으로 사용하고 있습니다. 그 이유는 readTrack :: String -> Track(readFile filename) :: IO String이기 때문입니다. 당신이 원하는 경우

, 당신은 당신이 알아서 다음 >>= print 또는 >>= writeFile newfilename 수있다.

data Track =... 사용 후에 deriving Show을 추가하는 것을 잊지 말고 type Track = ....을 사용할 필요는 없습니다.

+0

@ user1683526 1 주일 이상 숙제를했다고 생각합니다. 다음 번에 곧바로 시작하십시오. 정말 좋은 솔루션을 작성하고 많은 것을 배우고 어려움을 철저히 제거 할 시간이 있습니다. 하스켈은 프로그래밍 할 수있는 훌륭한 언어이지만, 효과적으로 사용하기 위해서는 많이 배워야합니다. 더 많이 생각하고, 적게 쓰지만 더 좋습니다. – AndrewC

관련 문제