18

The following snippet compiles:

{-# LANGUAGE TypeFamilies #-}
type family Foo a b

f :: (Foo a b ~ Int) => a -> b -> b
f = error ""

but infix type operators seem to behave differently:

{-# LANGUAGE TypeFamilies #-}
type family a \\ b

f :: (a \\ b ~ Int) => a -> b -> b
f = error ""

GHC complains that the second argument to \\ should have kind *, but b ~ Int has kind Constraint. Of course this can be fixed with parens, but I'm wondering if there's another way.

I've tried setting the precedence of my operator with the fixity declaration infixl 9 \\, but that doesn't fix the problem, indicating that the precedence of ~ is at least 9 (if I'm interpreting that correctly). I tried using the trick from this answer to make GHCi tell me the precedence of ~, but it didn't work.

Technically speaking, ~ probably isn't a type operator, it's more of a lexical construct similar to ,, but the questions still stand:

  1. Why do infix and prefix operators exhibit different behavior?
  2. Why does ~ bind so tightly?
  3. Is there something I can do to make my own operators bind even tighter?

(Note: This question asks about the precedence of type functions, but it doesn't say anything about ~.)

Community
  • 1
  • 1
crockeea
  • 21,651
  • 10
  • 48
  • 101
  • Another odd thing is that if I ask GHCi `:k (~)`, it tells me `(~) :: k -> k -> Constraint`, but if I ask `:i (~)`, it tells me `parse error on input ‘~’`. So something seems to be very strange about how the parser handles `~`. – dfeuer Feb 01 '15 at 01:40
  • I'm not certain what the cause of this is - `~` has some special behaviors due to being a built-in type function, and maybe it should be consistent with other things. But if this really bothers you, you can do something like `type (==) = (~); infixr 0 ==`, which would even be more syntactically consistent between term and type level. – user2407038 Feb 01 '15 at 05:20
  • I've got a [GHC ticket](https://ghc.haskell.org/trac/ghc/ticket/10056) now – crockeea Feb 01 '15 at 17:33

1 Answers1

1

~ isn't an operator, it's a keyword, like module or case, so I think you could only alter the precedence using parentheses.

See more here: https://wiki.haskell.org/Keywords#.7E

lightandlight
  • 1,345
  • 3
  • 10
  • 24