2014-06-06 3 views
3

마지막으로 태그가없는 스타일의 디스크에서 데이터 구조를 deserialize합니다. 즉마지막으로 태그없는 구문 분석 및 재귀 모 듈 동작

class SYM repl where 
    a :: repl 
    include :: FilePath -> repl 

myParser :: SYM r => Parser r 

나는 구문 분석하는 지시문을 포함하고 있습니다.

모나드 변환기가 아닌 attoparsec을 사용 중이므로 Loader = FilePath -> IO (Maybe Text) 유형을 제공 할 수 없습니다.

나는 포함을 해결하는 다음 SYM 인스턴스와 함께 인터프리터를 작성할 수 있습니다.

instance SYM r => SYM (Loader -> IO (Either String r)) where 
    include path loader = 
     maybe (Left "cannot load") (parseOnly myParser) <$> loader path 

불행히도 포함 된 파일에 포함 된 내용은 해결되지 않습니다. 물론 나는 다음 레이어를 해결하기 위해 두 번 해결할 수 있습니다. 그러나 그것은 모든 가능한 수준에서 그렇게하고 싶다면 무한한 유형으로 인도합니다.

지금은 (포함 HashMap)에 포함 된 모든 미리로드하고 그래서 나는 FilePath -> Maybe Text을 파서에 전달하고 거기에 포함하지만 해결할 수 있지만 분명히 최적은 아닙니다. (포함하면 더 이상 SYM의 일부가 아닙니다.)

제 질문은 마침내 태그없는 스타일이 그 문제를 어떻게 처리합니까?

편집는 : http://lpaste.net/105182

+1

'myParser' 함수가 올바르게 보이지 않습니다. 'Parser (Loader -> IO (어느 쪽의 String r))'를 포함하는 인클루드 인스턴스를 사용하면 (자) 원하는 것입니까? 'parseOnly'는 무엇입니까? –

+0

'parseOnly'는 Attoparsec에서 온 것입니다. 그리고 네, 그것이 파서의 유형이라고 생각합니다. 최종 인코딩의 표현은 그렇게 보일 것입니다. 내 더 큰 예제에서 사이에 newtype했다. 나는 최소한의 모범을 보일 것이다. – ibotty

+2

당신은 이미이 문제를 해결할 방법을 찾았습니다 : newtype에서 인스턴스 유형을 랩 한 다음 무한 재귀 적으로 만들 수 있다고 생각합니다. 이론적으로'include's는 실제로 무한 할 수 있으므로, 당신은 그 가능성을 다뤄야 할 것입니다. 또는 자신의 newtype을 만드는 대신 자유로운 모나드를 사용하여 각 해상도 계층을 처리 할 수 ​​있습니다. 보통 가능할 때마다 무료 모나드를 피하려고 노력하지만 YMMV는 가능합니다. –

답변

1

그것은 돌이켜 보면 꽤 쉬웠다하지만, 보통 : 나는 lpaste에 완전한 예를 발표했다.

1 레벨 전용 해결은 간단히 다음과 같습니다.

instance SYM r => SYM (Loader -> IO (Either String r)) where 
    token t _ = return . Right $ token t 
    include path loader = 
     maybe (Left "cannot load") (parseOnly myParser) <$> loader path 

.l.e. 성공적으로로드 된 파일에서 parseOnly myParser :: Either String r을 실행합니다.

결의-모든 것 바로 myParser에 대한 SYM (Loader -> IO (Either String r)) 인스턴스를 선택하고 loader 인수를 추가해야합니다 결정적인 단계가 새로 parseOnly D SYM에 추가 매개 변수 로더를 제공 할 것입니다

include path loader = 
     maybe (return $ Left "cannot load") 
       (either (return ∘ Left) ($ loader) . parseOnly myParser) 
       =<< loader path 

을 repl, 따라서 올바른 인스턴스를 선택하십시오.

전체 스 니펫은 주석이 달린 람다 페이스트에 있습니다 : http://lpaste.net/105182. "include include token"을 입력하여 테스트하십시오.