2016-12-14 10 views
1

하스켈에서 단위 테스트를 작성하면 undefined에 도달 할 때 표현식이 실패해야합니다. 약간 까다 롭습니다. 아무 소용이하스켈에서 lazy expression으로 평가되지 않은 undefined 평가 유닛

module Main where 

import Test.Hspec 
import Control.Exception (evaluate) 

main :: IO() 
main = hspec $ do 
    describe "Test" $ do 
    it "test case" $ do 
     evaluate (take 1 $ map (+1) [undefined, 2, 3]) `shouldThrow` anyException 

: 나는 HSpec와 ​​함께 다음 시도했다.

[*** Exception: Prelude.undefined 
CallStack (from HasCallStack): 
    error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err 
    undefined, called at <interactive>:2:20 in interactive:Ghci1 

답변

4

문제는 evaluate는 NH 에 식을 강제하거나 WHNF1하지 않는다는 것입니다 : 내가 REPL에서 같은 표현을 평가하는 경우, 내가 얻을 것 나에게 did not get expected exception: SomeException

를보고 . GHCi에서 x <- evaluate (take 1 $ map (+1) [undefined, 2, 3])을 사용해보세요. 오류가 발생하지 않습니다. evaluate (take 1 $ map (+1) [undefined, 2, 3])에 붙여 넣을 때 유일한 이유는 GHCi가 얻은 결과를 인쇄하려고 시도하기 때문입니다. 그렇게하기 위해 표현을 평가하려고합니다. 당신이 볼 수 있듯이,

ghci> x <- evaluate (take 1 $ map (+1) [undefined, 2, 3]) 
ghci> :sprint x 
x = [_] 

evaluatex을 실현하기 위해 충분히 표현을 강요되지 않았습니다

당신이 평가되었습니다 얼마나 썽크보고 싶다면, 당신은 항상 GHCi에서 :sprint을 사용할 수 있습니다 undefined이 포함되어 있습니다. 빠른 수정은 force을 사용하여 정상적인 형태로 검사중인 것을 평가하는 것입니다.

import Test.Hspec 
import Control.Exception (evaluate) 
import Control.DeepSeq (force) 

main :: IO() 
main = hspec $ do 
    describe "Test" $ do 
    it "test case" $ do 
     evaluate (force (take 1 $ map (+1) [undefined, 2, 3] :: [Int])) 
     `shouldThrow` anyException 

force는 인수가 평가 가득 찰 때까지 당신이 썽크의 평가를 트리거 할 수 있습니다. NFData ("표준 양식 데이터"의 약자) 제약 조건이 있으므로 데이터 구조에 대해 GenericNFData이라는 파생어를 발견 할 수 있습니다. evaluatehead $ map (+1) [undefined, 2, 3] 오류를 트리거 않는 이유입니다 WNHF에 인수를 밀어한다는 것을 지적 @AlexisKing에 대한


1 감사합니다. take의 경우에는 충분하지 않습니다.

+0

이 답변은 좋지만 WHNF에 대한 인수를 평가한다고 명확하게 명시되어있을 때'evaluate'이 WHNF로 평가되지 않는다고 말할 때 혼란 스럽습니다. (https://hackage.haskell.org /package/base-4.9.0.0/docs/Control-Exception.html#v:evaluate). –

+0

@AlexisKing 나는 정정! 어쨌든 WNHF만으로는 충분하지 않으므로 'NFData'가 필요한 이유는 무엇입니까? – Alec

+0

사실, 정의되지 않은 단일 요소가있는 목록을 생성하기 때문에 테스트가 통과됩니까? (+1) 기능이 적용되지 않는 이유는 무엇입니까? –