2011-04-19 11 views
2

사용자가 ID, 너비, 높이 및 설명 사각형을 제공 한 다음 파일에 쓸 수 있습니다. 이제 파일에서 내 프로그램에이 콘텐츠를로드하고 싶지만 오류가 있습니다.하스켈 프로그램에서 유형 오류

예상 유형 [RectangleType]을 유추 유형 IO [Rectangletype]과 비교할 수 없습니다. menuRectangles의 첫 번째 인수 즉, db. 식 MenuRectangles db. do 표현식 메뉴에서 DB를 봅니다.

무슨 일입니까? [직사각형 2~5 6 "ABCABC"직사각형 1 2 4 "ABCABC"]

이것은 코드 :

import IO 
import Char 
import System.Exit 
import Maybe 


data RectangleType = Rectangle Int Int Int deriving(Show, Read) 


loadFile :: FilePath -> IO [RectangleType] 
loadFile fname = 
    catch (do fileContent <- readFile fname 
       return (read fileContent) 
    ) errorHandler 
    where 
     errorHandler e = do putStrLn ("Error file") 
          exitFailure 

db = loadFile "db.txt" 


main = do 
    putStrLn "Choose option:" 
    n <- getLine 
    case n of 
     "1"   -> do menuRectangles db; main 
     "2"   -> putStrLn "bye, bye" 
     otherwise -> do putStrLn "Bad option"; main 


menuRectangles :: [RectangleType] -> IO [RectangleType] 
menuRectangles rs = do 
    putStrLn "Please choose option:" 
    putStrLn "1 - Add rectangle" 
    putStrLn "2 - Show rectangle" 
    putStrLn "3 - Quit" 
    putStr "Number: " 
    n <- getLine 
    case n of 
     "1"   -> do { {- rs_new <- addRectangle rs; -} menuRectangles rs }; 
     "2"   -> do { {- showRectangle rs; -} menuRectangles rs } 
     "3"   -> do { putStrLn "Quitting"; return rs } 
     otherwise -> do { putStrLn "The End"; return rs } 

EDIT : 올바른 코드 :

이 내 파일의 콘텐츠이다
import IO 
import Char 
import System.Exit 
import Maybe 


data RectangleType = Rectangle Int Int Int deriving(Show, Read) 


loadFile :: FilePath -> IO [RectangleType] 
loadFile fname = 
    catch (do fileContent <- readFile fname 
       return (read fileContent) 
    ) errorHandler 
    where 
     errorHandler e = do putStrLn ("Error file") 
          exitFailure 


main = do 
    db <- loadFile "db.txt" 
    mainMenu db 


mainMenu rs = do 
    putStrLn "Choose option:" 
    n <- getLine 
    case n of 
     "1"   -> do menuRectangles rs; mainMenu rs 
     "2"   -> putStrLn "bye, bye" 
     otherwise -> do putStrLn "Bad option"; mainMenu rs 


menuRectangles :: [RectangleType] -> IO [RectangleType] 
menuRectangles rs = do 
    putStrLn "Please choose option:" 
    putStrLn "1 - Add rectangle" 
    putStrLn "2 - Show rectangle" 
    putStrLn "3 - Quit" 
    putStr "Number: " 
    n <- getLine 
    case n of 
     "1"   -> do { {- rs_new <- addRectangle rs; -} menuRectangles rs }; 
     "2"   -> do { {- showRectangle rs; -} menuRectangles rs } 
     "3"   -> do { putStrLn "Quitting"; return rs } 
     otherwise -> do { putStrLn "The End"; return rs } 
+0

왜 게시물에 여전히 잘못된 코드는? – Arjan

+0

아마도 질문과 대답이 여전히 의미가 있습니다. –

답변

5

하스켈에는 순수 코드라는 개념이 있습니다. 순수 코드에는 사용자 입력 값, 시스템 호출, 의사 난수 생성, 비 순수 코드 호출 등이 포함되지 않습니다.

순수 함수는 항상 항상 항상 동일한 동작을 보장합니다. 프로그램의 어휘 적 콘텐츠 (예 : 그들은 다른 값을 반환 할 수 있지만, 다른 값을 반환하는 이유는 "세상"에 의존 할 수 없습니다).

이것은 기능적 언어에서 매우 강력한 정책이며 매우 강력한 코드를 허용합니다. 예를 들어 함수를 호출해도 관련없는 전역 변수 나 다른 데이터 구조의 상태는 변경되지 않는다는 것을 알고 있습니다. 나는 종종이 정책을 파이썬 코드에 적용한다.

하스켈이 순도 불순물을 시행하는 방식은 IO 모나드입니다.

"세계"가 터치되는 항목은 IO 모나드에 래핑되어 값이 "오염 된"것으로 나타났습니다. 이 "오염 된"값을 만지는 것이 있으면 반환하는 값도 오염되어 있어야합니다.

IO 모나드에서 순수 코드를 실행해야 해당 값에 액세스 할 수 있습니다. IO 모나드 내에서 읽은 값을 "풀어서"순수 코드로 전달하면 순수 코드가 값을 반환하고 값을 인쇄 할 수 있습니다. 모든 것이 예상대로 작동하지만 IO 모나드에서해야합니다.

대부분의 코드가 IO 모나드 외부의 순수하고 기능적인 형식으로 작성되도록하는 것이 좋습니다. 예 : 순수한 doStuffWithRectangles 함수는 IO 모나드에서 호출됩니다.

아름다운 점은 순수 코드가 Rectangle 값이 IO Rectangle 유형으로 인해 오염되었음을 알 필요가 없다는 것입니다. IO 모나드에서 작업하는 한, 순수 코드는 보통의 것일뿐입니다. Rectangle.


그리고 바로이 응답을 더 명시 적으로 만들 수 : 그 일을 "세계"(파일 시스템)에서 온 있기 때문에 예를 들어 당신이 프로그램을 실행하는 동안 파일을 변경 한 경우 IO 모나드에 싸여 readFile 반환 일, 다른 값을 리턴 할 수 있습니다.

--db = loadFile "db.txt" REMOVED-- 

main = do --within the IO monad 
    putStrLn "Choose option:" 
    n <- getLine 
    **DB <- LOADFILE "db.txt"** --db is now a pure value 
    case n of 
     "1"   -> do menuRectangles db; main 
     "2"   -> putStrLn "bye, bye" 
     otherwise -> do putStrLn "Bad option"; main 

더 많은 정보 : http://www.haskell.org/tutorial/io.html

좋은 온라인 읽기/offile : http://learnyouahaskell.com/ 또한

좋은 온라인/offile 읽어 http://book.realworldhaskell.org/

+0

지금까지 질문에서 알 수 있듯이 OP는 이미 IO 개념을 알고 있습니다. 어쩌면 그는 그 단일 서명을 잊어 버린 것일 수도 있습니다. – fuz

+0

ninjagecko unfortunatelly 코드가 작동하지 않습니다. 나는 내 코드를 변경했고 지금은 작동한다. (unfortunatelly 나는 주석으로 코드를 작성하는 방법을 모른다. 모든 코드가 한 줄로되어있는 이유는 무엇인가?) : 'main = do db <- loadFile "db.txt" 에는 mainMenu의 DB 에는 mainMenu의 RS는 = 는 putStrLn "옵션 선택"할 N <- "1"의 getline 경우 N을 -> menuRectangles의 RS을; mainMenu rs "2"-> putStrLn "bye, bye" 그렇지 않으면 -> 할 putStrLn "잘못된 옵션"; mainMenu rs' – mrquestion

+0

'** DB <- LOADFILE "을 추가 한 줄을 알고 있다고 가정합니다. db.txt"** "는 형식 및 대소 문자로 인해 유효하지 않은 하스켈 코드입니다. 나는 stackoverflow가 코드를 포맷하는 방식을 읽을 수 없기 때문에 불행히도 말할 수 없다. 그리고 'mainMenu'가 이전에 없었던 많은 장소에 추가되었다는 사실. 다행히도 그것을 고칠 수 있었지만 필요한 최소한의 변화를 아는 것은 좋을 것입니다. =) – ninjagecko