2017-01-30 132 views
0

我定義了一個在哪裏定義名稱earthSecondsAYear。可悲的是,它無法在前面的where子句的範圍內。秒其中名稱不在前面範圍內

下面是代碼:

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 

錯誤消息:

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

我缺少什麼?

+1

'where'只適用於它上面的定義(所以'planetYearSecs Earth = 100')。這一直咬着我。 :) – Alec

回答

3

A where子句綁定到單個模式匹配,並且不更寬。它確實在多個守衛條款,如在綁定:

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

這可能會導致您認爲它適用於整個函數定義。但是在這裏的第一個方程中,您不能使用y,就像您在問題的第一個方程中不能使用earthSecondsAYear一樣,因爲您只將它與最後一個方程綁定。

然而,修復很簡單:不是引入新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子句中的所有定義都可以看到所有的邊界值,所以你的第一個方程將很高興地使用你上一個方程中定義的值。