This is a summary from Yet Another Haskell Tutorial
https://learnxinyminutes.com/docs/pt-br/haskell-pt/
Lazy, pure functional programming language.
- It is called lazy because expressions which are not needed to determine the answer to a problem are not evaluated.
- The opposite of lazy is strict, which is the evaluation strategy of most common programming languages.
- Haskell is called pure because it does not allow side effects (A side effect is something that affects the "state" of the world.
- Haskell uses a system of monads to isolate all impure computations from the rest of the program and perform them in the safe way.
- Haskell is called a functional language because the evaluation of a program is equivalent to evaluating a function in the pure mathematical sense.
In September of 1987 a meeting was held at the conference on Functional Programming Languages and Computer Architecture (FPCA '87) in Portland, Oregon.
There was a strong consensus at this meeting that more widespread use of this class of functional languages was being hampered by the lack of a common language. It was decided that a committee should be formed to design such a language, providing faster communication of new ideas, a stable foundation for real applications development, and a vehicle through which others would be encouraged to use functional languages.
This document describes the result of that committee's efforts: a purely functional programming language called Haskell, named after the logician Haskell B. Curry whose work provides the logical basis for much of ours.
- Write more bug-free code in less time using Haskell than other language.
- Very readable and extensible.
- Hugs - very fast to load files, slow to run them; implements almost all of Haskell 98 (the standard) and most extensions; built-in support for module browsing; cannot create stand-alones; written in C; works on almost every platform; built-in graphics library.
- GHC - interactive environment is slower than Hugs to load, but allows function definitions in the environment (in Hugs you have to put them in a file); implements all of Haskell 98 and extensions; good support for interfacing with other languages; in a sense the "de facto" standard. It also allows compiled objects to be loaded and tested.
- NHC - less used and no interactive environment, but produces smaller and often faster executables than does GHC; supports Haskell98 and some extensions.
ghc --make Main.hs -o main
What is unusual is that Haskell requires that the names given to functions and values begin with a lower-case letter and that the names given to types begin with an upper-case letter. The moral is: if your otherwise correct program won't compile, be sure you haven't named your function Foo, or something else beginning with a capital letter.
Haskell eschews side effects. A side effect is essentially something that happens in the course of executing a function that is not related to the output produced by that function.
For instance, in a language like C or Java, you are able to modify "global" variables from within a function. This is a side effect because the modification of this global variable is not related to the output produced by the function. Furthermore, modifying the state of the real world is considered a side effect: printing something to the screen, reading a file, etc., are all side effecting operations.
Functions that do not have side effects are called pure. An easy test for whether or not a function is pure is to ask yourself a simple question: "Does this function's result depend only on the arguments it receives, and is returning a result the only thing it does?"
All of this means that if you're used to writing code in an imperative language (like C or Java), you're going to have to start thinking differently. Most importantly, if you have a value x, you must not think of x as a register, a memory location or anything else of that nature. x is simply a name, just as "Hal" is my name. You cannot arbitrarily decide to store a different person in my name any more than you can arbitrarily decide to store a different value in x. This means that code that might look like the following C code is invalid (and has no counterpart) in Haskell:
int x = 5;
x = x + 1;
A call like x = x + 1
is called destructive update because we are destroying whatever was in x before and replacing it with a new value. Destructive update does not exist in Haskell.
Prelude> 5*4+3
23
Prelude> 5^5-2
3123
Prelude> sqrt 2
1.4142135623730951
Prelude> 5*(4+3)
35
Prelude> fst (5, "hello")
5
Prelude> snd (5, "hello")
"hello"
Prelude> 0:[1,2]
[0,1,2]
Prelude> 5:[1,2,3,4]
[5,1,2,3,4]
Prelude> 5:1:2:3:4:[]
[5,1,2,3,4]
The colon is called the "cons" operator; the process of adding an element is called "consing." The etymology of this is that we are constructing a new list from an element and an old list. We can see the cons operator in action in the following examples:
Prelude> 0:[1,2]
[0,1,2]
Prelude> 5:[1,2,3,4]
[5,1,2,3,4]
Prelude> length [1,2,3,4,10]
5
Prelude> head [1,2,3,4,10]
1
Prelude> length (tail [1,2,3,4,10])
4
In Haskell, a String is simply a list of Chars
Prelude> 'H':'e':'l':'l':'o':[]
"Hello"
Prelude> "Hello " ++ "World"
"Hello World"
Prelude> "Five squared is " ++ show (5*5)
"Five squared is 25"
Prelude> read "5" + 3
8
Prelude> read "Hello" + 3
Program error: Prelude.read: no parse
Prelude> map Data.Char.toUpper "Hello World"
"HELLO WORLD"
Prelude> filter Data.Char.isLower "Hello World"
"elloorld"
´foldr´ takes three arguments: a function, an initial value and a list. The best way to think about foldr is that it replaces occurrences of the list cons operator (:) with the function parameter and replaces the empty list constructor ([]) with the initial value. Thus, if we have a list:
Prelude> foldr (+) 0 [3,8,12,5]
28
Prelude> foldr (*) 1 [4,8,5]
160
Prelude> foldr (-) 1 [4,8,5]
0
square x = x * x
signum x =
if x < 0
then -1
else if x > 0
then 1
else 0
f x =
case x of
0 -> 1
1 -> 5
2 -> 2
_ -> -1
Using let
roots a b c =
let discr = sqrt (b*b - 4*a*c)
twice_a = 2*a
in ((-b + discr) / twice_a,
(-b - discr) / twice_a)
Test> square (f 1)
25
Test> square (f 2)
4
Test> f (square 1)
5
Test> f (square 2)
-1
In mathematics we write f . g to mean "f following g," in Haskell we write f . g also to mean "f following g".
Test> (square . f) 1
25
Test> (square . f) 2
4
Test> (f . square) 1
5
Test> (f . square) 2
-1