我想定义一个对某些类型具有专用实现而对所有其他类型具有通用实现的函数,它比{-#SPECIALIZE#-}具有更多的魔力,或者重写规则可以帮助我。 (大概,我想尽可能地从IORef
切换到Ptr
。)
封闭类型族可能会提供解决方案:
type family Specialized a where
Specialized Foo = Bar
Specialized a = Baz
...但是目前尚不清楚如何从这里构建函数special :: Specialized a
或类似的东西。封闭类型族似乎在类型级别上起作用,但是我不知道如何在数据级别上做适当的事情。
如果我愿意明确列出我不想专门研究的所有类型,则可以编写一个类型类,并为所有其他类型制作一个instance
,但是我想写一些专门用于类型的有限列表,然后对 all 其他类型进行其他操作。
我该如何完成这样的事情?
答案 0 :(得分:2)
您可以使用重叠的类来完成它。这是编写nub
的示例,当列表为整数列表时,它会选择一种更有效的容器类型:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
import Data.Set (Set)
import qualified Data.Set as Set
type family Container a where
Container Int = IntSet
Container a = Set a
class Monoid (Container a) => Uniqable a where
insert :: a -> Container a -> Container a
member :: a -> Container a -> Bool
instance Uniqable Int where
insert = IntSet.insert
member = IntSet.member
instance {-# OVERLAPPABLE #-} (Ord a, Container a ~ Set a) => Uniqable a where
insert = Set.insert
member = Set.member
uniq :: Uniqable a => [a] -> [a]
uniq xs = foldr f (const []) xs mempty
where
f x a s
| member x s = a s
| otherwise = x : a (insert x s)