2017-01-04 8 views
1

Rasa、私のテキストエディタで作業していますが、Yi.Ropeを使用して低レベルのテキスト操作のほとんどを行っていますが、拡張機能を開発する人にはより良いインターフェイスを公開したいと思います。ロープ、文字列、またはテキストを使用するように人を制限するのではなく、人々が自分が望むものを使用できるようにするだけの理由は何ですか?だから私は、テキストの共通分母を使用して、テキスト・タイプの間で移動することができます。このタイプのクラスを書いた:関数の型レベル最適化

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 

今私の外部API関数は次のように制約を使用することができます。myFunc :: TextLike a => a -> ...制約といずれかから変換することtextConvert内部を呼び出します任意のTextLikeにTextLike。これは実際にはうまくいきますが、内部ではYiString構造を使用しており、仲介者はTextであるため、このテクニックを使って関数を呼び出すときはいつでもYiStringからYiStringに変換しますが、textConvertの実装は実際にYiStringをTextに変換し、次にTextをYiStringに戻します。これは明らかに非効率です:

私は同様の種類の一般性(最良の方法が何であれ)。特定のケース、特に特殊ケースtextConvert :: YiString -> YiStringを最適化したいと思います。誰でも良い方法を知っていますか?たぶん、タイプレベルのプログラミング、多分別のアプローチがありますか?

ありがとうございます!

+0

このような状況に遭遇したため、機能への追加機能を厳密には避けてください。関数は一度定義され、多くの場所で使用されます。呼び出し元は、関数の構成などを使用して関数を適合させることができます。もしあなたがTextインタフェイスを持っていると思えば、あなたは通常のAPIをText変換してラップする '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