封闭型系列和奇怪的功能类型

时间:2014-10-29 22:12:51

标签: haskell type-families

抱歉,我无法想象这个问题有更好的标题,所以请提前阅读。想象一下,我们有一个封闭类型的族,它将每种类型映射到它的相应Maybe,除了maybes本身:

type family Family x where
  Family (Maybe x) = Maybe x
  Family x = Maybe x

我们甚至可以使用该类型族声明一个函数:

doMagic :: a -> Family a
doMagic = undefined

exampleA = doMagic $ Just ()
exampleB = doMagic $ ()

在GHCi中使用它表明可以评估此​​函数应用程序的类型:

*Strange> :t exampleA      
exampleA :: Maybe ()       
*Strange> :t exampleB      
exampleB :: Maybe ()       

问题是,除了doMagic之外,是否可以提供undefined函数的任何实现?比如说我想把每个值都包装成一个Just构造函数,除了Maybes应该保持原样,我怎么能这样做呢?我尝试使用类型类,但如果不使用封闭类型系列,则无法为doMagic函数编写可编译签名,有人可以帮助我吗?

2 个答案:

答案 0 :(得分:8)

您可以使用其他封闭类型系列来区分Maybe xx,然后您可以使用另一个类型类为这两种情况提供doMagic的单独实现。快速而肮脏的版本:

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses,
    FlexibleInstances, UndecidableInstances, ScopedTypeVariables #-}

type family Family x where
  Family (Maybe x) = Maybe x
  Family x = Maybe x

data True
data False

type family IsMaybe x where
  IsMaybe (Maybe x) = True
  IsMaybe x = False


class DoMagic a where
  doMagic :: a -> Family a

instance (DoMagic' (IsMaybe a) a (Family a)) => DoMagic a where
  doMagic = doMagic' (undefined :: IsMaybe a)   


class DoMagic' i a r where
  doMagic' :: i -> a -> r

instance DoMagic' True (Maybe a) (Maybe a) where
  doMagic' _ = id

instance DoMagic' False a (Maybe a) where
  doMagic' _ = Just


exampleA = doMagic $ Just ()
exampleB = doMagic $ ()

答案 1 :(得分:4)

你可以做出一个蹒跚而行的doMagic函数。不幸的是,这个类型家庭的封闭对你来说并没有多大帮助。这是一个开始的样子

{-# LANGUAGE TypeFamilies #-}

type family Family x where
    Family (Maybe x) = Maybe x
    Family x = Maybe x

class Magical a where doMagic :: a -> Family a
instance Magical (Maybe a) where doMagic = id
instance Magical () where doMagic = Just

你可以看到它正如你所说的那样在ghci中工作:

*Main> doMagic $ Just ()
Just ()
*Main> doMagic $ ()
Just ()

那么为什么我说它一直在蹒跚而行呢?好吧,你可能已经注意到这两个提供的实例并不涵盖Haskell类型的大部分生态系统:

*Main> doMagic $ True
<interactive>:3:1:
    No instance for (Magical Bool) arising from a use of ‘doMagic’
    In the expression: doMagic
    In the expression: doMagic $ True
    In an equation for ‘it’: it = doMagic $ True

因此,必须为每个感兴趣的类型(构造函数)提供实例。事实上,即使是不连贯的实例 - 许多此类问题可以被提交的俱乐部 - 在这里也有帮助;如果有人试着写

instance Magical (Maybe a) where doMagic = id
instance Magical a where doMagic = Just

编译器正确地抱怨说,毕竟我们不知道完全多态的实例实际上是正确的类型。关于不连贯实例的事情是编译器告诉我们,只是因为那是选择的实例,其他实例肯定适用。所以我们有可能在某个时候选择完全多态的实例,后来发现我们真的是幕后的Maybe,然后我们只包了一层{{1}在事物周围。不幸的。

目前没有太多可以做的事情。目前封闭式家庭并不提供人们可能希望获得的所有知识。也许有一天,GHC将提供一种机制,使封闭式家庭在这方面更有用,例如类型不等式约束,但我不会屏住呼吸:如何提供这些有用的信息是一个研究问题,我没有听到任何有关人们处理它的谣言。