2017-01-30 9 views
0

名前を定義する場所を定義しましたearthSecondsAYear。悲しいことに、それは前のwhere節の範囲に収まらない。私は何をしないのですsecondここでnameは前のwhere句の範囲にはありません

:14:34: error: 
    Variable not in scope: earthSecondsAYear 

module SpaceAge (Planet(..), ageOn) where 

data Planet = Mercury 
      | Venus 
      | Earth 
      | Mars 
      | Jupiter 
      | Saturn 
      | Uranus 
      | Neptune 

ageOn :: Planet -> Float -> Float 
ageOn planet seconds = (seconds/100) * planetYearSecs planet 
where planetYearSecs Mercury = (earthSecondsAYear/100) * 0.2408 
     planetYearSecs Venus = 0.6151 
     planetYearSecs Mars = 1.8808 
     planetYearSecs Jupiter = 11.8626 
     planetYearSecs Saturn = 29.4474 
     planetYearSecs Uranus = 84.0168 
     planetYearSecs Neptune = 164.7913 
     planetYearSecs Earth = 100 
     where earthSecondsAYear = 31557600 

エラーメッセージ:ここに

は、コードのですか?

+1

'where'は' planetYearSecs Earth = 100'のすぐ上の定義にのみ適用されます。これはいつも私をかむ。 :) – Alec

答えて

3

where節は、1つのパターンマッチにバインドします。

foo :: Int -> Int 
foo 0 = 0 
foo x | y < 30 = 5 
     | otherwise = y 
    where y = x * x 

あなたはそれが全体の関数定義に適用されると考えさせることがあります。それは、そのような中など、複数のガード条項、全体でバインドを行います。しかし、最後の方程式にのみ結びついているので、質問の最初の方程式にearthSecondsAYearを使用できないのと同じように、ここで最初の方程式にはyを使用できませんでした。

しかし、修正は簡単です:代わりに新しいwhere句を導入するのは、単に既存のwhere句に別の定義を追加します。

ageOn :: Planet -> Float -> Float 
ageOn planet seconds = (seconds/100) * planetYearSecs planet 
where planetYearSecs Mercury = (earthSecondsAYear/100) * 0.2408 
     planetYearSecs Venus = 0.6151 
     planetYearSecs Mars = 1.8808 
     planetYearSecs Jupiter = 11.8626 
     planetYearSecs Saturn = 29.4474 
     planetYearSecs Uranus = 84.0168 
     planetYearSecs Neptune = 164.7913 
     planetYearSecs Earth = 100 
     earthSecondsAYear = 31557600 

ちょうど、where句で複数のバインディングを定義することは完全に合法ですそれらをすべて同じレベルにインデントすることによってそして、あなたがするとき、where句の中のすべての定義はすべてのバインドされた値を見ることができるので、最初の方程式は最後の方程式で定義された値をうまく使用します。

関連する問題