[GHC] #14104: Pattern synonyms work where constructors fail

GHC ghc-devs at haskell.org
Thu Aug 10 08:58:38 UTC 2017


#14104: Pattern synonyms work where constructors fail
-------------------------------------+-------------------------------------
           Reporter:  Iceland_jack   |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.2.1
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 This may be a bug.

 Taken from
 [https://www.reddit.com/r/haskell/comments/6so95h/why_do_pattern_synonyms_work_here_when/
 reddit thread]:

 {{{#!hs
 {-# LANGUAGE DataKinds, FlexibleInstances, GADTs, MultiParamTypeClasses,
              PatternSynonyms, TupleSections, TypeFamilies,
              TypeFamilyDependencies, TypeOperators, ViewPatterns #-}
 -- ...
 type family Sum (ts :: [*]) = (t :: *) | t -> ts where
   Sum (t ': ts) = Either t (Sum ts)
   Sum '[] = Void

 pattern At :: (KnownNatural n, Index n ts) => SNatural n -> (ts !! n) ->
 Sum ts
 pattern At sn t <- (at -> Just (sn, t)) where At = toSum

 at :: (KnownNatural n, Index n ts) => Sum ts -> Maybe (SNatural n, ts !!
 n)
 at = fmap (sn,) . ofSum sn where sn = knownNatural

 class Index (n :: Natural) (ts :: [*]) where
   type (!!) ts n :: *
   toSum :: SNatural n -> (ts !! n) -> Sum ts
   ofSum :: SNatural n -> Sum ts -> Maybe (ts !! n)

 instance Index n ts => Index ('Succ n) (t ': ts) where
   type (!!) (t ': ts) ('Succ n) = ts !! n
   toSum (SSucc sn) = Right . toSum sn
   ofSum (SSucc sn) = either (const Nothing) (ofSum sn)

 instance Index 'Zero (t ': ts) where
   type (!!) (t ': ts) 'Zero = t
   toSum SZero = Left
   ofSum SZero = either Just (const Nothing)

 data Natural = Zero | Succ Natural

 data SNatural (n :: Natural) where
   SZero :: SNatural 'Zero
   SSucc :: SNatural n -> SNatural ('Succ n)

 class KnownNatural (n :: Natural) where
   knownNatural :: SNatural n
 instance KnownNatural 'Zero where
   knownNatural = SZero
 instance KnownNatural n => KnownNatural ('Succ n) where
   knownNatural = SSucc knownNatural
 }}}

 Using `SZero`, `SSucc SZero`, ... fails

 {{{#!hs
 type Trit = Sum '[(), (), ()]

 fromTrit :: Trit -> Int
 fromTrit (At SZero ()) = 0
 fromTrit (At (SSucc SZero) ()) = 1
 fromTrit (At (SSucc (SSucc SZero)) ()) = 2
 }}}

 but making pattern synonyms succeeds

 {{{#!hs
 pattern S0 :: SNatural 'Zero
 pattern S0 = SZero

 pattern S1 :: SNatural ('Succ 'Zero)
 pattern S1 = SSucc S0

 pattern S2 :: SNatural ('Succ ('Succ 'Zero))
 pattern S2 = SSucc S1

 type Trit = Sum '[(), (), ()]

 fromTrit :: Trit -> Int
 fromTrit (At S0 ()) = 0
 fromTrit (At S1 ()) = 1
 fromTrit (At S2 ()) = 2
 }}}

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14104>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list