Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this type definition illegal?

Tags:

haskell

I'm writing an interpreter for a small programming language, and the AST looks something like this:

data Value a = IntVal a Int | FloatVal a Float
data Expr a = AddExpr a (Value a) (Value a) | MulExpr a (Value a) (Value a)

I use parameter a for storing the line number of each term. Some functions take terms with annotations, and some take empty terms (replacing a with unit), like this:

myFunction :: Value Int -> ...
myFunction = ...

myOtherFunction :: Value () -> ...
myOtherFunction = ...

However, I find this alternative a bit more clear:

type Annotated b = b Int
type Bare b = b ()

Then, I can rewrite the previous two functions like this:

myFunction :: Annotated Value -> ...
myFunction = ...

myOtherFunction :: Bare Value -> ...
myOtherFunction = ...

This works great, however I also need to define a synonym for a list type with the same characteristics:

type MyList a = [Value a]

Now, I want to define a function taking an annotated MyList like so:

myOtherOtherFunction :: Annotated MyList -> ...
myOtherOtherFunction = ...

However, this doesn't work. The error says The type synonym ‘MyList’ should have 1 argument, but has been given none. Why doesn't this work? Is there any better way to define these types? Maybe with some extension?

like image 304
Alejandro De Cicco Avatar asked Dec 30 '22 12:12

Alejandro De Cicco


1 Answers

Haskell is by default a bit pedantic that type synonyms must always be fully applied, i.e. you can't mention MyList without directly applying it to a concrete type parameter, thus you can't have Annotated MyList. The reason for this restriction is that partially applied type synonyms could be misused to form a Turing-complete language. Oops... that would be a pain for the compiler.

That said, clearly this is a bit silly for Annotated MyList, which is after resolved with two simple substitutions to the perfectly unspectacular [Value Int], so that should work, shouldn't it? And indeed it does, but you need to enable a syntactic extension:

{-# LANGUAGE LiberalTypeSynonyms #-}

myOtherOtherFunction :: Annotated MyList -> ...
myOtherOtherFunction = undefined
like image 69
leftaroundabout Avatar answered Jan 31 '23 13:01

leftaroundabout