2016-11-06 2 views
3

나는 하스켈을 배워야 할 것입니다. 그래서 아마 아주 사소한 것이지만, 어떻게 다시 작성하고 어떻게 작동하는지에 대한 몇 가지 조언을 해주시면 감사하겠습니다.리팩터링 where 절

내가 작업 코드 (사용 패키지 : HTF, ParsecFlow) : 다음 한

{-# OPTIONS_GHC -F -pgmF htfpp #-} 
{-# LANGUAGE FlexibleContexts #-} 

module Main where 

import Test.Framework -- assertEqual, assertBool, htfMain, htf_thisModulesTests 
import Text.ParserCombinators.Parsec (eof, spaces, parse) 
import Flow ((|>)) 
import Data.Either (isLeft) 

whiteSpaces = spaces 

test_parse_whitespace = do 
    mapM_ positive [ 
     "", " ", "\t", "\n", "\r\n", " \r\n ", 
     " \t \r\n \t \n \r \t " 
    ] 
    mapM_ negative ["x", " x", "x ", " x ", "\t_\t"] 
    where 
    parser = whiteSpaces >> eof 
    parseIt = parse parser "" 
    positive str = assertEqual (parseIt str) (Right()) 
    negative str = assertBool (parseIt str |> isLeft) 

main :: IO() 
main = htfMain htf_thisModulesTests 

내가 어디 부분이 거의 동일한이 새로운 테스트를 추가하고, 그래서 이런 식으로 리팩토링하는 시도를 :

pos_neg_case parser = do 
    return [positive, negative] 
    where 
    fullParser = parser >> eof 
    parseIt = parse fullParser "" 
    positive str = assertEqual (parseIt str) (Right()) 
    negative str = assertBool (parseIt str |> isLeft) 

test_parse_whitespace' = do 
    mapM_ positive [ 
     "", " ", "\t", "\n", "\r\n", " \r\n ", 
     " \t \r\n \t \n \r \t " 
    ] 
    mapM_ negative ["x", " x", "x ", " x ", "\t_\t"] 
    where 
    [positive, negative] = pos_neg_case whiteSpaces 

컴파일러가 제안하는대로 lang. 기능을 설정해도 작동하지 않는 기능은 작동하지 않습니다.

Couldn't match expected type ‘[Char] -> m b0’ 
      with actual type ‘[String -> IO()]’ 
Relevant bindings include 
    test_parse_whitespace' :: m() (bound at test/Spec.hs:21:1) 
In the first argument of ‘mapM_’, namely ‘positive’ 
In a stmt of a 'do' block: 
    mapM_ positive ["", " ", "\t", "\n", ....] 

Couldn't match expected type ‘[Char] -> m b1’ 
      with actual type ‘[String -> IO()]’ 
Relevant bindings include 
    test_parse_whitespace' :: m() (bound at test/Spec.hs:21:1) 
In the first argument of ‘mapM_’, namely ‘negative’ 
In a stmt of a 'do' block: 
    mapM_ negative ["x", " x", "x ", " x ", ....] 
+1

assertEqual 및 assertBool은 [* HTF *] (http://hackage.haskell.org/package/HTF-0.13.1.0/docs/Test-Framework-HUnitWrapper.html) 패키지이고'(|>)'는 [* flow *] (https://hackage.haskell.org/package/flow-1.0.7/docs/Flow .html)'flip ($)'과'(&)'의 동의어 일 뿐이다. (사용하지 않는 잘 알려지지 않은 패키지를 언급하면 ​​더 명확한 질문을하게됩니다.) – duplode

+0

@duplode 오, 고맙습니다 (수입이 충분하다고 생각했습니다). 나는 * 흐름 *이 하스 켈러들 사이에서별로 인기가 없다는 것을 알았지 만, HTF *도 그렇게하지 않았는가? 상용구없이 모듈의 모든 단위 테스트를 실행할 수있는 더 나은 대안이 있습니까? – monnef

+0

"수입이 충분하다고 생각했습니다."- 검색과 검색에 필요한 충분한 정보를 제공하고 관련 기능을 찾는다는 의미에서 충분합니다. 독자의 질문에 대한 편의성 문제 일뿐입니다. (나는 당신이 사용한 꾸러미들에 대해 아무 말도하지 않습니다.) – duplode

답변

0

, 문제가 있던 return 당신은에 추가 mapM으로 전달되므로 pos_neg_case을 목록으로 돌려주고 싶으면 목록에 배치하는 것 이상을 수행 할 필요가 없습니다. return는 (는) 키워드가 아닙니다. 모나드 컨텍스트에 값을 주입하는 함수 일뿐입니다. 그런 주입을 할 필요가 없다면 return이 필요하지 않습니다.

답변을 인용 P.S : :

그러나 나는 구멍이 매우 복잡 꼬추 Text.Parsec.Prim.ParsecT s() Data.Functor.Identity.Identity a -> [s -> IO()]을 나에게주고 있었다, 파서 유형을 추측했다.

이것은 아주 일반적인 패턴의 예입니다. 은 형식 변수가 많은 형식 생성자이고 Parser은 이러한 변수 중 일부의 일반적인 선택 집합에 대한 형식 동의어이며이를 명시 적으로 언급하지 않는 계층 서명 형식을 허용합니다. 당신이 documentation에 대한 보면 차례가에 ... 당신이 Parser 그냥 의미 발견 할 것이다,

type Parser = Parsec String() 

... 그리고 Parsec을 (인덱스는 경우에 많은 도움) 또는 GHCi에서 :info를 사용 ...

type Parsec s u = ParsecT s u Identity 

... 그래서 Parser 동의어를 확대하는 GHC 당신이 유형의 구멍을 도입 할 때 말한 것입니다 ParsecT String() Identity을 준다.

+0

설명 해 주셔서 감사합니다 :). – monnef

0

나는 여전히 그 모나드에 대해 잘 모르겠지만, 나는 그것이 어떻게 든 일하고 있어요 (typeholes 일명 그 _ 그들에 대해 알고하지 않았다 많은 도움).

pos_neg_case :: Parser a -> [String -> IO()] 
pos_neg_case parser = [positive, negative] 
    where 
    fullParser = parser >> eof 
    parseIt = parse fullParser "" 
    positive str = assertEqual (parseIt str) (Right()) 
    negative str = assertBool (parseIt str |> isLeft) 

는하지만, 파서 유형을 추측했다 구멍이 나에게 매우 복잡한 꼬추를주고 있었다 - Text.Parsec.Prim.ParsecT s() Data.Functor.Identity.Identity a -> [s -> IO()]합니다.

pos_neg_case parser = do 
    return [positive, negative] 
    where -- etc. 

mapM_의 유형은 다음과 같습니다 :

GHCi> :t mapM_ 
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m() 

positivenegative 이미로 적합한 유형이 함수입니다 당신이다시피