Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,274
    • Issues 4,274
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 412
    • Merge Requests 412
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #14499

Closed
Open
Opened Nov 21, 2017 by Icelandjack@IcelandjackReporter

Pattern synonym, (a::k) cannot be written (a::N) given (k ~ N)

I was trying to create a pattern synonym that matches TypeRep (a::k) when k ~ N, witnessing the equality and returning the representation.

This works fine:

{-# Language PatternSynonyms, ViewPatterns, GADTs, ConstraintKinds, RankNTypes, KindSignatures, PolyKinds, ScopedTypeVariables, DataKinds, TypeInType, TypeOperators, TypeApplications #-}

import Type.Reflection
import Data.Kind

foo :: forall (kind::k') (a::k). TypeRep kind -> TypeRep a -> Maybe (kind :~~: k, TypeRep a)
foo krep rep = do

  HRefl <- eqTypeRep krep (typeRepKind rep)

  pure (HRefl, rep)

data N = O | S N

pattern Bloop :: forall (a::k). () => N~k => TypeRep (a::k) -> TypeRep (a::k)
pattern Bloop rep <- (foo (typeRep @N) -> Just (HRefl, rep :: TypeRep (a::N)))
  where Bloop rep = rep

Note that I have annotated rep :: TypeRep (a::N) in the view pattern, which is the first argument to Bloop.

Let's reflect that in the type

-- error:
-- • Expected kind ‘N’, but ‘a’ has kind ‘k’
-- • In the first argument of ‘TypeRep’, namely ‘(a :: N)’
--   In the type ‘TypeRep (a :: N) -> TypeRep (a :: k)’
--    |
-- 15 | pattern Bloop :: forall (a::k). () => N ~ k => TypeRep (a::N) -> TypeRep (a::k)
--    |                                                         ^

pattern Bloop :: forall (a::k). () => N~k => TypeRep (a::N) -> TypeRep (a::k)
pattern Bloop rep <- (foo (typeRep @N) -> Just (rep, HRefl))
  where Bloop rep = rep

Oh no, GHC complains that a::k (not a::N) but we have local knowledge that N ~ k. I know the rules for kinds are weird so I don't know if this is intended.

A way around this is quantifying over an existential variable that is heterogeneously equal to a:

pattern Bloop :: forall (a::k). () => forall (n::N). a~~n => TypeRep (n::N) -> TypeRep (a::k)
Trac metadata
Trac field Value
Version 8.2.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#14499