4

Why cannot one define operator := in GHC? Can this limitation be eliminated in future releases?

Here is output:

[1 of 1] Compiling Images           ( Images.hs, interpreted )

Images.hs:19:1:
    Invalid type signature: (:=) :: HasSetter s => s a -> a -> IO ()
    Should be of form <variable> :: <type>
danbst
  • 3,363
  • 18
  • 38
  • 1
    You can't use colons in operators. See http://stackoverflow.com/questions/10548170/what-characters-are-permitted-for-haskell-operators – jcarpenter2 Feb 08 '14 at 02:48
  • 4
    Names beginning with `:` are reserved for the datatype namespace: `data (:=) a b = (:=) a b` – user2407038 Feb 08 '14 at 03:06
  • But function space and datatype space do not interchange. Why not allow := for functions, not only constructors? There will be some tricky things to distinguish it from list cons, though – danbst Feb 08 '14 at 03:19
  • 2
    @danbst, Haskell doesn't allow type/data constructors and functions to have the same name format in general. For example, type/data constructors must begin with a capital (or :) and function names must begin with a lowercase (or a valid value-level operator character). You can use `.=` or `=:` as an infix function name though. – David Young Feb 08 '14 at 03:50
  • 7
    Essentially, colons are "uppercase" for the purpose of the naming rule. – Ben Feb 08 '14 at 03:54
  • 6
    @danbst The function space and the data constructor space *absolutely* overlap. All data constructors are functions. The ability to distinguish data constructors from other values syntactically is required for the way Haskell specifies pattern matches. – Carl Feb 08 '14 at 04:02
  • 2
    @jcarpenter You can use colons in operators, just not at the beginning. For example, `(=:) = ()` is a valid definition. – Gabriella Gonzalez Feb 08 '14 at 10:04

1 Answers1

9

Constructors vs functions

Constructors make new data types out of old data. Let's roll our own list:

data List a = Empty | Cons a (List a)

myList = Const 1 (Cons 2 Empty) -- 1:2:[] =[1,2]

uncons x' (Cons x xs) = if x == x' then xs else Cons x xs

Here, Cons :: a -> List a is a special function that takes an element and a list and makes a longer list.

It's important that there's a difference between constructor functions and ordinary functions, so that the compiler knows which one is valid in a pattern match:

headM (Cons x xs) = Just x
headM Empty = Nothing

That makes sense, but this doesn't:

previousHead (uncons x xs) = Just x
previousHead xs = Nothing

because how can the computer know which element you removed or whether you did remove one?

Infix Constructors and functions

Sometimes, as with lists, it's helpful to have a constructor work infix, so we actually have the equivalent of

data [a] = [] | a:[a]

so we can write lists like 1:2:[].

Infix functions need to be separate from identifiers so we can write x:xs unambiguously without spaces, so infix functions (including infix constructors like : have to consist entirely of symbols, not letters.

The compiler still needs to be able to tell constructors apart from ordinary functions when they're infix, so we need the equivalent of the rule that constructors start with a capital. The language designers designated : as the only capital symbol, so infix constructors have to start with it, and ordinary functions can't.

What you can do with :=

You can use := as a constructor, so you could define

data Assignment a = Variable := Expression a

But if you want to call an ordinary function :=, you can't, because : isn't allowed at the front as it counts as the capital symbol, you'd have to start with something else, for (simple but pointless) example:

(.:=) :: Maybe a -> a -> Maybe a
Nothing .:= x   = Just x
Just y  .:= x   = Just x
not my job
  • 642
  • 10
  • 21