Skip to content

(:>) vs. Cons #2913

Open
Open
@kleinreact

Description

@kleinreact

I recognized that

mymap :: (a -> b) -> Vec n a -> Vec n b
mymap _ Nil           = Nil
mymap f (x `Cons` xr) = f x `Cons` mymap f xr

type-checks, but

mymap' :: (a -> b) -> Vec n a -> Vec n b
mymap' _ Nil       = Nil
mymap' f (x :> xr) = f x :> mymap' f xr

does not (GHC 9.10):

<interactive>:4:11: error: [GHC-25897]
    • Couldn't match type ‘n’ with ‘n0 + 1’
      Expected: Vec n a
        Actual: Vec (n0 + 1) a
      ‘n’ is a rigid type variable bound by
        the type signature for:
          mymap' :: forall a b (n :: Nat). (a -> b) -> Vec n a -> Vec n b
        at <interactive>:2:1-40
    • In the pattern: x :> xr
      In an equation for ‘mymap'’:
          mymap' f (x :> xr) = f x :> mymap' f xr
    • Relevant bindings include
        mymap' :: (a -> b) -> Vec n a -> Vec n b
          (bound at <interactive>:3:1)

This is kind of annoying, as up to my knowledge most people use (:>) and are not much aware about Cons. A little research revealed that there already was a discussion about this in the past (#170, #966, #867, #943), but that discussion was within the scope of some old GHC (we don't even support any more). Thus, it might be that these past considerations need some re-evaluation first.

My primary question would be: "Do we still need both: Cons and (:>) these days?"


A possible solution would be to update the (:>) synonym to

pattern (:>) ::
  forall n a. () =>
  forall m. n ~ m + 1 =>
  a -> Vec m a -> Vec n a
pattern (:>) x xs = Cons x xs

which elides the aforementioned type-mismatch (and yes, the explicit quantifier split is necessary here). However, this change also introduces a different quantifier alternation than Cons, which might be non-desirable.

Another solution (my favorite) would be to just rename Cons to (:>) and to drop Cons, as I could not find any counterexample, where this solution would cause any trouble, i.e., where using the constructor directly breaks things.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions