 Continuo da qui, copio qui, scrollare fino a “Infix and Prefix Application”.

Applicazioni infisse e prefisse
Functions like `+` and `*` are binary functions, that is, functions which expect exactly two arguments, just like our `average` function:

`average a b = (a + b) / 2.0`

When we want to apply `average`, we first write the function name and then the arguments

``````Prelude> average 6.9 7.25
7.075``````

while with addition and multiplication, we place the function in-between the arguments:

``````Prelude> 1 + 5
6
Prelude> 3.4 * 7.2
24.48``````

We call the former notation prefix, as the function appears before the arguments, and the latter infix, as it is in-between its argument. We can easily convert an infix function into a prefix one by simply placing it in parenthesis:

``````Prelude> (+) 1 5
6
Prelude> (*) 3.4 7.2
24.48``````

and conversely, we can use a regular binary function as infix operator by placing its name between backquotes:

``````Prelude> 6.9  `average` 7.25
7.075``````

Nota: ``` con Linux lo ottengo con AltGr’ con Windows non lo so.

Binary functions in backquotes are, by default, left associative, this means that multiple applications, as in

``````Prelude> 6.9 `average` 7.25 `average` 3.4
5.2375``````

are implicitely grouped to the left; so, the above expression is the same as

``````Prelude> (6.9 `average` 7.25) `average` 3.4
5.2375``````

Which notation you use is a matter of style. In general, people can parse arithmetic expressions much more easily if they are in infix notation.

All serious programming languages provide some functions whose argument types are not restricted to a single type, but instead a whole family of types is admitted. For example, both `1 + 2` (where the arguments are of type `Int`) as well as `1.5 + 1.2` (where the arguments are of type `Float`) make sense. Consequently, the function `+` simultaneously has the type

`(+) :: Int -> Int -> Int`

as well as the type

`(+) :: Float -> Float -> Float`

We call functions, such as `+`, overloaded functions; the name of an overloaded function carries more than just one meaning as witnessed by the multiplicity of type signatures. The motivation for permitting overloaded functions, such as `+`, is that it would be awkward to enforce the use of two different symbols —that is, two different function names— for the two cases of adding integers or adding floating-point numbers. (Note that Haskell requires us to use the prefix notation of an operator in a type signature; i.e., we write `(+)` and not just `+`.)

Unfortunately, all of this means that, given our current knowledge, we cannot denote the type of `+` in a single type signature of the form `(+) :: type`; instead, we have to resort to a family of type signatures (one for each possible type of `+`). To improve on this, we need to consider additional notation, where we exploit the fact that both argument types and the result type in one particular use of `+` are always identical. In other words, we might say that `+` has type `a -> a -> a` where `a` is either `Int` or `Float`. In fact, Haskell does not restrict a to only `Int` or `Float`, but instead allows any numeric type (most of which we have not encountered yet). We denote the set of numeric types by `Num` and generally call such sets of types type classes.

Using the type class `Num`, we can specify the type of `+` to be `a -> a -> a`, where the type `a` is a member of set `Num`, or, using mathematical notation `a ∈ Num`. Haskell abbreviates `a ∈ Num` to `Num a` and places it in front of the function type separated by a double arrow `=>`. Hence, the closed form of the type signature for `+` is

`(+) :: Num a => a -> a -> a`

Other binary arithmetic operations, such as `-` and `*`, have the same type. Note how types, such as `Int` and `Float`, as well as type classes, such as `Num`, have names starting with an upper case letter, whereas place holders, such as `a`, have names starting with a lower case letter. This convention simplifies reading type signatures and is enforced in Haskell. We call place holders in types, such as a above, type variables. They are important in programming languages that have a sophisticated type system.

In addition to `Num`, another important type class is `Eq`. It contains all those types for which the function `==` is defined, which checks whether its two arguments are equal. All types that we have encountered so far, except function types, are part of `Eq`. So, all of the following make sense:

``````Prelude> 2 == 2
True
Prelude> 5.0 == 6.0
False
Prelude> ("Hello " ++ "World!") == "Hello World!"
True``````

The type of `==` is

`(==) :: Eq a => a -> a -> Bool`

where `Bool` is the type of Boolean values `False` and `True`.

Another important type class is `Show`. It contains all types for which the system knows how to convert them to a string representation, and the most important function of this class of values is the `show` function:

``````Prelude> show 123
"123"
Prelude> show 1.75
"1.75"
Prelude> show False
"False"
Prelude> show "False"
"\"False\""``````

It is important to note that the `Int` value `123` and the string `"123"` are two fundamentally different objects, same for the boolean value `False` and the string `"False"`. As we can see in the last example, if we apply show to a value which is already a string, it returns a different string, containing the opening and closing quotes as additional characters.

Functions are not in the type class `Show`, so if we try and apply `show` to the function `inc`, for example, the compiler will complain:

``````Prelude> inc x = x + 1
Prelude> show inc

:18:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘show’
(maybe you haven't applied a function to enough arguments?)
• In the expression: show inc
In an equation for ‘it’: it = show inc``````

The compiler message `No instance for (Show (Int -> Int))` means that the type `Int -> Int` is (so far) not in in the type class `Show`. We will later see that we can extend type classes, and the compiler suggests to do so as a fix

The function `show` is also invoked whenever we enter an expression […] at the GHCi prompt: after the expression is evaluated, the system tries to convert it to a string using the `show` function, so it can print it. Therefore, if we just enter a function […] at the GHCi prompt, we will see a similar error message. All this is illustrated in the following screencast. Ahemmm… il video si può vedre di là. Ma i preferisco il testo; prossimamente… 😉

Frequently used type classes and overloaded functions. We will cover type classes and overloading in more detail in later chapters. For now, here is an overview of some frequently used type classes, and some overloaded operations on these type classes.

Typeclass `Show`

• functions: `show :: Show a => a -> String`: convert the given value into a string.
• member types: almost all predefined types, excluding function types.

Typeclass `Eq`

• functions: `(==), (/=) :: Eq a => a -> a -> Bool`: equality and inequality.
• member types: almost all predefined types, excluding function types.

Typeclass `Ord`

• functions: `(<), (>), (<=), (>=) :: Ord a => a -> a-> Bool`: less than, greater than, less or equal, greater or equal
• member types: almost all predefined types, excluding function types.
• all types in `Ord` are already in `Eq`, so if you are using both `==` and `<` on a value, it is sufficient to require it to be in `Ord`.

Typeclass `Num`

• functions: `(+), (-), (*) :: Num a => a -> a -> a`: arithmetic operations.
• member types: `Float`, `Double`, `Int`, `Integer`.

Typeclass `Integral`

• functions: `div, mod :: Integral a => a -> a -> a`: division.
• member types: `Int` (fixed precision), `Integer` (arbitrary precision)

Typeclass `Fractional`

• functions: `(/) :: Fractional a => a -> a -> a`: division.
• member types: `Float`, `Double`

Typeclass `Floating`

functions: `sin`, `cos`, `tan`, `exp`, `sqrt , ... :: Floating a => a -> a`: trigonometric and other functions.

member types: `Float`, `Double`

We will introduce more type classes and operations as we use them. If you want to find out more about a type class, select its name and type `:info TYPECLASS-NAME` in GHCi.

``````Prelude> :info Integral
class (Real a, Enum a) => Integral a where
quot :: a -> a -> a
rem :: a -> a -> a
div :: a -> a -> a
mod :: a -> a -> a
quotRem :: a -> a -> (a, a)
divMod :: a -> a -> (a, a)
toInteger :: a -> Integer
{-# MINIMAL quotRem, toInteger #-}
-- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’``````

Nota: ho eliminanto i riferimenti al Mac, non frequento macisti 😜

🤢

Posta un commento o usa questo indirizzo per il trackback.