2017-01-04 3 views
1

저는 텍스트 편집기 인 Rasa을 작업 중이며 Yi.Rope을 사용하여 저급 텍스트 조작을 대부분하고 있지만 확장 기능을 개발하는 사람들에게 더 좋은 인터페이스를 제공하고 싶습니다. . 로프, 문자열 또는 텍스트를 사용하도록 사람들을 제한하는 대신 사람들이 원하는 것을 사용하게하지 않는 이유를 알았습니다. 이제 내 외부 API 함수와 같은 제약 사용할 수 있습니다함수의 유형 수준 최적화

import Control.Lens 
import qualified Yi.Rope as Y 
import qualified Data.Text as T 

class TextLike a where 
    toText :: a -> T.Text 
    fromText :: T.Text -> a 
    asText :: Iso' a T.Text 
    asText = iso toText fromText 

instance TextLike Y.YiString where 
    toText = Y.toText 
    fromText = Y.fromText 

instance TextLike T.Text where 
    toText = id 
    fromText = id 

instance TextLike [Char] where 
    toText = T.pack 
    fromText = T.unpack 

textConvert :: (TextLike a, TextLike b) => a -> b 
textConvert = fromText . toText 

: myFunc :: TextLike a => a -> ... 제약을하고 변환하는 내부 textConvert를 호출 그래서 일반적인 텍스트의 분모를 사용하여 텍스트 유형 간 이동 허용이 타입 클래스를 썼다 TextLike to 모든 TextLike. 이것은 실제로 꽤 잘 작동하지만 내 내부는 YiString 구조를 사용하고 중개자는 텍스트이기 때문에; 이 기술을 사용하여 함수를 호출 할 때 YiString을 YiString으로 변환하지만 textConvert의 구현은 실제로 YiString을 텍스트로 변환 한 다음 YiString으로 텍스트를 역으로 변환합니다. 분명히 비효율적입니다 : P

비슷한 종류의 보편성 (최선의 방법이 무엇이든). 특정 사례를 최적화하고 싶습니다. 특히 특별한 경우 textConvert :: YiString -> YiString. 누구든지 좋은 방법을 알고 있습니까? 어쩌면 타입 레벨 프로그래밍, 아마도 다른 접근 방식일까요?

감사합니다.

+0

이와 같은 상황에 처했기 때문에 기능에 대한 추가 기능을 피하십시오. 함수는 한 번 정의되어 여러 위치에서 사용됩니다. 호출자는 함수 구성을 사용하여 함수를 적용 할 수 있습니다. Text 인터페이스를 사용하는 것이 도움이된다고 생각한다면 일반 API를 텍스트 변환으로 단순히 래핑하는'Rasa.Text'와 같은 모듈을 추가 할 수 있습니다. – erisco

+0

이 형식 클래스는 좋은 생각인지 모르겠지만 [이 질문] (http://stackoverflow.com/questions/32130011/how-do-you-write-rewrite-rules-for-typeclass-methods) 유용 할 수 있습니다. – Alec

+0

GHC에서 ['fromIntegral'] (https://www.stackage.org/haddock/lts-7.14/base-4.9.0.0/src/GHC-Real.html#fromIntegral)에서 어떻게 수행되었는지 살펴보아야합니다.) – user2407038

답변

3

나는 그것을 테스트하지 않은,하지만이 최적화를 위해 재 작성 규칙을 사용할 수 있어야합니다 :

textConvert :: (TextLike a, TextLike b) => a -> b 
textConvert = fromText . toText 
{-# INLINE [1] textConvert #-} 

{-# RULES 
"toTextY/fromTextY" forall x. textConvert (x :: Y.YiString) = x 
#-} 

이 효과적으로 모든 비효율적 인 변환을 대체합니다. 나중에 -ddump-rule-firings 플래그로 컴파일하여이 규칙이 실행되는지 확인할 수 있습니다. 다음은 다시 쓰기 규칙에 대한 모든 세부 정보를 제공하는 자습서입니다. https://wiki.haskell.org/GHC/Using_rules