Closed type families and strange function types

点点圈 提交于 2020-01-22 14:27:20

问题


Sorry, I couldn't imagine any better title for the question, so please read ahead. Imagine that we have a closed type family that maps every type to it's corresponding Maybe except maybes themselves:

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

We can even declare a function using that type family:

doMagic :: a -> Family a
doMagic = undefined

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

Playing with it in GHCi shows that it is ok to evaluate the type of this function application:

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

The question is if it is possible to provide any implementation of the doMagic function except undefined? Let's for example say that I would like to wrap every value into a Just constructor, except Maybes which should remain intact, how could I do that? I tried using typeclasses, but failed to write a compileable signature for doMagic function if not using closed type families, could somebody please help me?


回答1:


You can use another closed type family to distinguish Maybe x from x and then you can use another typeclass to provide separate implementations of doMagic for these two cases. Quick and dirty version:

{-# 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 $ ()



回答2:


You can sort of make a doMagic function that hobbles along. Unfortunately, closed-ness of the type family doesn't really help you much. Here's how a start might look

{-# 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

You can see it working in ghci just as you asked:

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

So why do I say it's hobbling along? Well, you may have noticed that the two provided instances don't cover very much of the Haskell ecosystem of types:

*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

So one would have to provide instances for every type (constructor) of interest. Indeed, not even incoherent instances -- the club with which many such problems can be beat into submission -- helps here; if one tries to write

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

the compiler rightly complains that after all we don't know that the fully polymorphic instance actually has the right type. The thing about incoherent instances is that we aren't told by the compiler that, just because that was the instance chosen, that the other instances definitely don't apply. So it's possible that we choose the fully polymorphic instance at some point, only to later discover that we were really a Maybe behind the scenes, and then we just wrapped one too many layers of Maybe around things. Unfortunate.

There is not much that can be done about this at the moment. Closed type families at the moment just do not provide all the knowledge one might wish to have available. Perhaps some day GHC will offer a mechanism that makes closed type families more useful in this regard such as a type inequality constraint, but I wouldn't hold my breath: it is a research problem how to provide this useful information, and I haven't heard any rumors of people tackling it.



来源:https://stackoverflow.com/questions/26641559/closed-type-families-and-strange-function-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!