2012-07-12 2 views
1

나는이 어려운 언어를 즐기고 있었고, 현재 학교 과제를 진행하고 있습니다.readIO 구문 분석 오류 haskell, this close

이것은 다음과 같습니다. 사용자에게 숫자 목록을 요구 한 다음 목록의 평균을 표시해야합니다. 알아낼 정도로 가깝습니다. 그러나 나는이 이상한 구문 분석 오류를 얻을 :

module Main (listM', diginums', getList, main) where 

import System.IO  
import Data.List 

diginums' = [] 
listM' = [1, 2, 3] 
average' = (sum diginums')/(fromIntegral (length diginums')) 
getList :: IO [Double] 
getList = readLn 

main = do 
     putStrLn "Please enter a few numbers" 
     diginums' <- getList 
     putStrLn $ show average' 

터미널 프롬프트 : 내가 입력 Enter a few #'s

: 123

ERROR : Exception: user error (Prelude.readIO: no parse) 

내가 내 기능을 알고 여기에

"Exception: user error (Prelude.readIO: no parse)" 

내 코드입니다 평균을 계산하기 위해 올바르게 작동합니다. 이제 내 문제는 사용자의 숫자 목록을 가져올 때 평균 함수에 대해 Double을 입력하기 위해 구문 분석을 올바르게 수행하지 않는다고 생각합니다.

+1

들여 쓰기를 무시해야하는 이유는 무엇입니까? 들여 쓰기를 여기에 맞게 만들면 많은 슬픔을 줄일 수 있습니다. –

+0

lol 나는 그것을 올바르게 만들려고 노력하지만 답변을 제출할 때마다 브라우저가 텍스트 패드에서 정확한 들여 쓰기를 망칠 것 같습니다 ... 죄송합니다! – Shawn

+0

들여 쓰기에 대해 이야기하는 동안 : (실제) 탭 대신 공백을 사용해야합니다. GHC가 탭을 8 칸으로 해석하기 때문에 모양이 좋은 레이아웃은 완전히 잘못되었을 수 있습니다. – Vitus

답변

3

귀하의 유형 서명은

getList :: IO [Double] 
getList = readLn 

이 양식

[123, 456.789, 1011.12e13] 

의 입력을 기대하지만 당신은 하나의 숫자로 읽을 수 무엇을 준 의미 Double s의 목록이 읽 말한다 , "123". 따라서 read이 실패하면 입력을 [Double]으로 구문 분석 할 수 없습니다.

문법적으로 올바른 Haskell 값 (예 : 공백으로 구분 된 숫자 목록)이 아닌 다른 형식으로 입력을 구문 분석하려면 readLn을 사용할 수 없지만 원하는 형식의 파서를 작성해야합니다 당신 자신. 아주 쉬운 숫자의 언급 공백으로 구분 된 목록, 예를 들어

getList :: IO [Double] 
getList = do 
    input <- getLine 
    let nums = words input 
    return $ map read nums 

당신이 숫자의 형태로 목록을 얻고 싶다면

, 당신은 좋겠 빈 라인으로 종료 한 줄, 각 누적 기와 함께 재귀를 사용하십시오.보다 복잡하거나 덜 엄격한 형식의 파서는 작성하기가 어려울 수 있습니다.

구문 분석이 고정되면 값을 변경할 수 없다는 사실에 익숙하지 않은 문제가 발생합니다.

diginums' = [] 
listM' = [1, 2, 3] 
average' = (sum diginums')/(fromIntegral (length diginums')) 

, 따라서 그 값이 NaN이다

sum diginums'/fromIntegral (length diginums') = 0/0 

이고, 상기 값 average'Double는 빈리스트 diginums'의 관점에서 정의 된 세 값을 정의한다.

당신이 필요로하는 것은 Double의리스트의 평균을 계산하고 그 값을 main에 입력 된리스트에 적용하는 함수입니다.

average :: [Double] -> Double 
average xs = sum xs/fromIntegral (length xs) 

main = do 
    putStrLn "Please enter a few numbers" 
    numbers <- getList 
    print $ average numbers 
+0

그냥 행운을 빕니다 입력 : [123, 456.789] # 괄호를 추가해야했습니다 : S 이상한 오류가 없지만 결과는 다음과 같습니다. NaN – Shawn

+2

예,'readLn'에 대괄호가 필요합니다. 구문의 일부입니다. 그 결과,'diginums '는 빈리스트이기 때문에 최상위 값'average''는'0/0'이므로'NaN'입니다. 읽기 목록을 바인드하는'main'의 로컬 이름은 완전히 무관합니다. –

+0

그것은 haskel에 당신의 knowledge를 믿을 수 없다, 나는 실제로 당신의 explaination에서 많은 것을 배웠다. 당신의 도움에 감사한다 나는 아직도 길다. 그러나 확실한 im는 내가 당신만큼 좋게 될 수있다라고 확신한다! 다시 한번 감사드립니다! – Shawn

3

하스켈에는 가변 변수가 없습니다,하지만 당신은 빈 목록으로 diginums'을 초기화 한 후 getList로 채우하려고하는 것 같습니다.

는 대신, 어쩌면 인수로 average'에 번호 목록을 전달하려면, 무엇인가 : 다니엘이 말한대로 또한

module Main (getList, main) where 

import System.IO 
import Data.List 


average' ds = (sum ds)/(fromIntegral (length ds)) 
getList :: IO [Double] 
getList = readLn 

main = do 
     putStrLn "Please enter a few numbers" 
     diginums' <- getList 
     putStrLn $ show $ average' diginums' 

, 당신은 길을 주어, 하스켈 리터럴리스트 구문을 사용하여 입력 할 필요가 당신은 그것을 코딩했습니다.