使用封闭类型族写函数“如果是A,则为X,否则为Y”

时间:2018-06-27 19:15:39

标签: haskell

我想定义一个对某些类型具有专用实现而对所有其他类型具有通用实现的函数,它比{-#SPECIALIZE#-}具有更多的魔力,或者重写规则可以帮助我。 (大概,我想尽可能地从IORef切换到Ptr。)

封闭类型族可能会提供解决方案:

type family Specialized a where
   Specialized Foo = Bar
   Specialized a = Baz

...但是目前尚不清楚如何从这里构建函数special :: Specialized a或类似的东西。封闭类型族似乎在类型级别上起作用,但是我不知道如何在数据级别上做适当的事情。

如果我愿意明确列出我不想专门研究的所有类型,则可以编写一个类型类,并为所有其他类型制作一个instance,但是我想写一些专门用于类型的有限列表,然后对 all 其他类型进行其他操作。

我该如何完成这样的事情?

1 个答案:

答案 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)
相关问题