为什么我不能在 Hspec 中找到“在哪里”工作
Why cannot I get `where` to work in Hspec
我在 do
块中与 where
的语义作斗争,特别是 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
的某种固有限制?
这是为 where 块的范围规则服务的句法限制。在 where
块中,模式匹配中绑定的值在范围内,并且 where
块中定义的值在该模式匹配中的守卫范围内。因此,必须将 where
块附加到至少可以存在模式匹配和守卫的位置。这最终成为值声明和 case 表达式的分支。在您的第二个示例中,您试图将 where
块附加到任意表达式,这不是他们打算做的。
where
子句只能 附加到函数或大小写绑定,并且必须位于右侧正文之后。
当编译器看到where
时,它就知道你的spec = ...
等式的RHS结束了。然后它使用缩进来计算 where
内的定义块延伸多远(在这种情况下只是单个 f = id
)。接下来,编译器正在寻找下一个模块范围定义的开始,但是缩进的 describe "bar" $ do
对于定义的开始是无效的,这是你得到的错误。
您不能随意将 where
子句插入函数定义的中间。它仅可用于在绑定的整个 RHS 范围内添加辅助绑定;它不能用于在任意子表达式的范围内添加局部绑定。
然而 let ... in ...
正是为了这个目的。并且由于您在每个 describe
下使用 do
块,您还可以使用 let
语句(使用 do
块的其余部分来分隔本地的范围绑定,而不是 let ... in ...
表达式的 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)
我在 do
块中与 where
的语义作斗争,特别是 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
的某种固有限制?
这是为 where 块的范围规则服务的句法限制。在 where
块中,模式匹配中绑定的值在范围内,并且 where
块中定义的值在该模式匹配中的守卫范围内。因此,必须将 where
块附加到至少可以存在模式匹配和守卫的位置。这最终成为值声明和 case 表达式的分支。在您的第二个示例中,您试图将 where
块附加到任意表达式,这不是他们打算做的。
where
子句只能 附加到函数或大小写绑定,并且必须位于右侧正文之后。
当编译器看到where
时,它就知道你的spec = ...
等式的RHS结束了。然后它使用缩进来计算 where
内的定义块延伸多远(在这种情况下只是单个 f = id
)。接下来,编译器正在寻找下一个模块范围定义的开始,但是缩进的 describe "bar" $ do
对于定义的开始是无效的,这是你得到的错误。
您不能随意将 where
子句插入函数定义的中间。它仅可用于在绑定的整个 RHS 范围内添加辅助绑定;它不能用于在任意子表达式的范围内添加局部绑定。
然而 let ... in ...
正是为了这个目的。并且由于您在每个 describe
下使用 do
块,您还可以使用 let
语句(使用 do
块的其余部分来分隔本地的范围绑定,而不是 let ... in ...
表达式的 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)