我正在努力解決塊where內的語意do,特別是Test.Hspec. 以下作業:
module ExampleSpec where
import Test.Hspec
import Test.QuickCheck
spec :: Spec
spec = do
describe "foo" $ do
let
f = id
in
it "id" $ property $
\x -> f x `shouldBe` (x :: Int)
describe "bar" $ do
it "id" $ property $
\x -> x `shouldBe` (x :: Int)
這不會:
module ExampleSpec where
import Test.Hspec
import Test.QuickCheck
spec :: Spec
spec = do
describe "foo" $ do
it "id" $ property $
\x -> f x `shouldBe` (x :: Int)
where
f = id
describe "bar" $ do
it "id" $ property $
\x -> x `shouldBe` (x :: Int)
它失敗了:
/mnt/c/haskell/chapter15/tests/ExampleSpec.hs:13:5: error: parse error on input ‘describe’
|
13 | describe "bar" $ do
| ^^^^^^^^
我做錯了什么還是這是某種固有的限制where?
uj5u.com熱心網友回復:
甲where子句可以僅被連接到一個功能或封面裝訂,并且必須位于右手側主體之后。
當編譯器看到 時where,它就知道spec = ...方程的 RHS結束了。然后它使用縮進來確定where擴展中的定義塊有多遠(f = id在這種情況下只是單個)。隨后編譯器正在尋找下一個模塊范圍定義的開始,但縮進describe "bar" $ do對于定義的開始無效,這是您得到的錯誤。
您不能where在函式定義的中間隨意插入子句。它只能用于在系結的整個 RHS 的范圍內添加輔助系結;它不能用于在任意子運算式的范圍內添加本地系結。
然而,正是let ... in ...為了這個目的。并且由于您do在 each 下使用塊describe,因此您還可以使用該let陳述句(使用do塊的其余部分來分隔本地系結的范圍,而不是運算式的in一部分let ... in ...)。所以你可以這樣做:
spec = do
describe "foo" $ do
let f = id
it "id" $ property $
\x -> f x `shouldBe` (x :: Int)
describe "bar" $ do
it "id" $ property $
\x -> x `shouldBe` (x :: Int)
uj5u.com熱心網友回復:
這是為 where 塊的范圍規則服務的句法限制。在where塊內,模式匹配中系結的值在范圍內,where塊中定義的值在該模式匹配中的保護范圍內。因此,where塊必須附加到至少可以存在模式匹配和守衛的位置。這最終成為值宣告和 case 運算式的分支。在你的第二個例子中,你試圖將一個where塊附加到一個任意運算式,這不是他們想要做的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/370603.html
