函数

时间:2017-01-04 06:06:33

标签: haskell

我正在使用Rasa,我的文本编辑器,我正在使用Yi.Rope进行大部分低级文本操作,但我想为人们提供一个更好的界面开发扩展。我没有限制人们使用绳索,字符串或文本,而是想到为什么不让人们使用他们想要的任何东西?所以我编写了这个类型类,它允许使用Text的公分母在文本类型之间移动:

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,这显然效率低下:P

我喜欢保持类似的普遍性(无论最好的方式是什么);但我想优化某些情况,特别是特殊情况textConvert :: YiString -> YiString。有人知道一个好方法吗?也许类型级编程,可能是一个完全不同的方法?

谢谢!

1 个答案:

答案 0 :(得分:4)

我还没有测试过,但您应该可以使用重写规则进行此优化:

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