# Let's see some code!

The code samples I've provided here are subject to not be valid in any future implementation of this language. I'm still trying to figure everything out, and it's hard to go back and change everywhere where I stated something about this language. So, I don't think things will change much, but they will be left here to preserve a record of progress, so I can see what this language really started out as.

## Literals

Here's what the literals look like:

Notice the types on the right of each literal expression. `Num`

,
`Complex`

, and `Fractional`

are all traits. The
type of these literals is similar to Haskell's typeclasses of the same
name. They represent the most general type that this literal can be. We'll
talk about traits in more detail in a later section. `Bool`

is a type with two constructors that take no arguments, `True`

and `False`

. `Lists`

and `Sets`

are
heterogenous, that is, they only hold objects of the same type. Lastly,
`String`

is *not* a trait like `Num`

and friends,
it is a proper class. It can be instantiated, and cannot be inherited from,
unlike traits. We'll talk about classes in more detail in a later section.

## Binary Operators

Here are some basic operators:

Even though we haven't talked about idk-lang's type language yet, we
will use it here for a quick showcase of some of the features of this
language. The type of `+`

is ```
Addable a => a ->
a -> a
```

. That is, `+`

takes in two objects of the
same type `a`

where the type `a`

must inherit the
trait `Addable`

. Since `Num`

and `String`

both inherit `Addable`

, the following expressions are both valid,

This shows one of the many advantages to using traits in a statically typed environment. It prevents the creation of over-engineered syntax to handle the “overloading” of operators on different types.

## Boolean Operators

Lastly, we have the boolean operators:

The operator `not`

has type `Bool -> Bool`

.
The operators `and`

and `or`

both have type
`Bool -> Bool -> Bool`

. These work as expected,
and because of how strict this language is, there is never an implicit
cast or coercion to any type, so these functions only work on booleans.

## Comparison Operators

We've seen some basic binary operators: `+ - / * ^`

. A valid
type for all of these operators is ```
Num a => a -> a ->
a
```

. That is, they take in two objects of the same type `a`

that implement the trait `Num`

, and return an object of type
`a`

that also implements that `Num`

. These are called
*Numeric operators*.

There is another group of operators called *Comparison operators*.
They all have type `a -> a -> Bool`

. That is, they take
in two objects, both of type `a`

and the and they return a
`Bool`

. Now, `a`

are *type variables*, they
represent any possible type. For example, the following operators are
*Comparison operators*

What is special about these operators is that they can be chained for greater expressive power. For example, this is a valid use of these operators,

These chains are equivalent to checking that every adjacent pair of
arguments to each operator returns

## Partial(ly applied) operators

Another cool feature of operators is that they can be partially applied, esentially equivalent to Haskell's operator sections except without any iterated section support. For example,

These can be really expressive when using maps or filters.

The next section is on *forms*,
where we'll talk about assignment, `if`

expressions, and
`where`

expressions.