Programowanie w systemie UNIX/Haskell: Różnice pomiędzy wersjami
m →Zobacz również: https://wiki.haskell.org/How_to_read_Haskell |
Nie podano opisu zmian |
||
Linia 52: | Linia 52: | ||
< |
<syntaxhighlight lang=haskell} |
||
-- https://pl.wikibooks.org/w/index.php?title=Programowanie_w_systemie_UNIX/Haskell&action=edit§ion=5 |
-- https://pl.wikibooks.org/w/index.php?title=Programowanie_w_systemie_UNIX/Haskell&action=edit§ion=5 |
||
> :set +m |
> :set +m |
||
Linia 60: | Linia 60: | ||
> a 1 |
> a 1 |
||
3 |
3 |
||
</syntaxhighlight> |
|||
</source> |
|||
Linia 74: | Linia 74: | ||
|valign="top" style="border-right:1px dashed SlateBlue"| |
|valign="top" style="border-right:1px dashed SlateBlue"| |
||
< |
<syntaxhighlight lang=haskell> |
||
-- Haskell |
-- Haskell |
||
square :: Int -> Int |
square :: Int -> Int |
||
square n = n*n |
square n = n*n |
||
</syntaxhighlight> |
|||
</source> |
|||
|valign="top" style="border-right:1px dashed SlateBlue"| |
|valign="top" style="border-right:1px dashed SlateBlue"| |
||
< |
<syntaxhighlight lang=c> |
||
// c |
// c |
||
int square(int n) { |
int square(int n) { |
||
return n*n; } |
return n*n; } |
||
</syntaxhighlight> |
|||
</source> |
|||
Linia 94: | Linia 94: | ||
* stylu pointfree |
* stylu pointfree |
||
< |
<syntaxhighlight lang=haskell> |
||
-- the '.' operator is used to compose functions |
-- the '.' operator is used to compose functions |
||
Linia 102: | Linia 102: | ||
-- the result is a descending sort |
-- the result is a descending sort |
||
countdown = desort [2,8,7,10,1,9,5,3,4,6] |
countdown = desort [2,8,7,10,1,9,5,3,4,6] |
||
</syntaxhighlight> |
|||
</source> |
|||
Porównanie: |
Porównanie: |
||
Linia 115: | Linia 115: | ||
|valign="top" style="border-right:1px dashed SlateBlue"| |
|valign="top" style="border-right:1px dashed SlateBlue"| |
||
< |
<syntaxhighlight lang=haskell> |
||
-- Haskell |
-- Haskell |
||
f . g -- pointfree style |
f . g -- pointfree style |
||
Linia 121: | Linia 121: | ||
f (g x) -- |
f (g x) -- |
||
( f . g ) (x) -- |
( f . g ) (x) -- |
||
</syntaxhighlight> |
|||
</source> |
|||
|valign="top" style="border-right:1px dashed SlateBlue"| |
|valign="top" style="border-right:1px dashed SlateBlue"| |
||
< |
<syntaxhighlight lang=c> |
||
// c |
// c |
||
f(g(x)) |
f(g(x)) |
||
</syntaxhighlight> |
|||
</source> |
|||
|} |
|} |
||
Linia 137: | Linia 137: | ||
Funkcja go<ref>[https://stackoverflow.com/questions/5844653/haskell-why-the-convention-to-name-a-helper-function-go stackoverflow question: haskell-why-the-convention-to-name-a-helper-function-go]</ref> |
Funkcja go<ref>[https://stackoverflow.com/questions/5844653/haskell-why-the-convention-to-name-a-helper-function-go stackoverflow question: haskell-why-the-convention-to-name-a-helper-function-go]</ref> |
||
< |
<syntaxhighlight lang=haskell> |
||
-- https://stackoverflow.com/questions/5926033/haskell-efficient-equivalent-of-for-loop |
-- https://stackoverflow.com/questions/5926033/haskell-efficient-equivalent-of-for-loop |
||
import System.IO |
import System.IO |
||
Linia 148: | Linia 148: | ||
main = loop 1000000 |
main = loop 1000000 |
||
</syntaxhighlight> |
|||
</source> |
|||
< |
<syntaxhighlight lang=haskell> |
||
-- https://gist.github.com/niorad/45187d9eb76c585e573e |
-- https://gist.github.com/niorad/45187d9eb76c585e573e |
||
divideBy x y = go x y 0 |
divideBy x y = go x y 0 |
||
Linia 158: | Linia 158: | ||
| a < b = (count, a) |
| a < b = (count, a) |
||
| otherwise = go (a - b) b (count + 1) |
| otherwise = go (a - b) b (count + 1) |
||
</syntaxhighlight> |
|||
</source> |
|||
Zmienna count jest pomocniczym licznikiem |
Zmienna count jest pomocniczym licznikiem |
||
Linia 182: | Linia 182: | ||
===cycle=== |
===cycle=== |
||
Cycle |
Cycle |
||
< |
<syntaxhighlight lang=haskell> |
||
ghci> take 10 (cycle [1,2,3]) -- weź 10 pierwszych elementów z listy cyklicznej utworzonej przez powtarzanie elementów listy [1,2,3] |
ghci> take 10 (cycle [1,2,3]) -- weź 10 pierwszych elementów z listy cyklicznej utworzonej przez powtarzanie elementów listy [1,2,3] |
||
[1,2,3,1,2,3,1,2,3,1] |
[1,2,3,1,2,3,1,2,3,1] |
||
ghci> take 12 (cycle "LOL ") |
ghci> take 12 (cycle "LOL ") |
||
"LOL LOL LOL " |
"LOL LOL LOL " |
||
</syntaxhighlight> |
|||
</source> |
|||
==Klasy== |
==Klasy== |
||
Linia 319: | Linia 319: | ||
Bardziej skomplikowany przykład, trójkąt Sierpińskiego: |
Bardziej skomplikowany przykład, trójkąt Sierpińskiego: |
||
< |
<syntaxhighlight lang=haskell> |
||
-- http://dev.stephendiehl.com/hask/#diagrams |
-- http://dev.stephendiehl.com/hask/#diagrams |
||
import Diagrams.Prelude |
import Diagrams.Prelude |
||
Linia 338: | Linia 338: | ||
main :: IO () |
main :: IO () |
||
main = defaultMain example |
main = defaultMain example |
||
</syntaxhighlight> |
|||
</source> |
|||
Uruchamiamy: |
Uruchamiamy: |
||
Linia 489: | Linia 489: | ||
przykład: |
przykład: |
||
< |
<syntaxhighlight lang=haskell> |
||
:info ($) |
:info ($) |
||
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’ |
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’ |
||
infixr 0 $ |
infixr 0 $ |
||
</syntaxhighlight> |
|||
</source> |
|||
Wersja z 15:31, 10 lut 2021
"A language that doesn't affect the way you think about programming, is not worth knowing. "[1]
Haskell zmieni twój sposób myślenia o programowaniu (:-))
Wykorzystuje teorię kategorii.[2]
Cechy Haskella
- jest to język czysto funkcyjny:[3]
- nie ma zmiennych w znaczeniu pojemników na wartości jak np. w C, są stałe (niewiadome jak w matematyce)
- nie ma efektów ubocznych
- lenistwo: obliczenia są wykonywane w momencie kiedy ich rezultat jest potrzebny, nie wcześniej. W efekcie możesz definiować nieskończone struktury danych, pod warunkiem, że nie używasz ich w całości.
- nie ma pętli (używa rekurencji)[4]
- funkcje wyższego rzędu - funkcje mogą być argumentami innych funkcji. Umożliwia to składanie przekształceń.
- polimorfizm
- klasy typów
- monady
Składnia
Instalacja
Potrzebujemy:
- kompilator/interpreter (GHC)
- menadżer pakietów (cabal)
- edytor (np. Gedit ma podświetlanie składni Haskella)
Metody:
- z użyciem standardowych instalatorów (stabilna, ale zwykle nie najnowsza wersja), np.:
- Centrum Oprogramowania Ubuntu
- Menadżer Pakietów Synaptic
- ręczna najnowszej wersji [7]
Przykłady
Funkcje
definicje
- w kodzie
- w osobnym pliku
let f :: a -> a ; f x = x -- GHCI , one line, signature let { fact 0 = 1 ; fact n = n * fact (n-1) } -- use braces with semicolons separating the definitions
:set +m
> let a 0 = 0
| a x = 1 + b x
| b x = 2 + a (x - 1)
> a 1
3
Kwadrat liczby
Przykład[8]
-- Haskell
square :: Int -> Int
square n = n*n
|
// c
int square(int n) {
return n*n; }
|
Złożenie (superpozycja) funkcji
Złożenie (superpozycja) funkcji ( ang. function composition) za pomocą:
- operatora . ( ang. dot operator)
- stylu pointfree
-- the '.' operator is used to compose functions
-- result of sort is pipelined to reverse
desort = (reverse . sort)
-- the result is a descending sort
countdown = desort [2,8,7,10,1,9,5,3,4,6]
Porównanie:
|
-- Haskell
f . g -- pointfree style
f . g x -- pointfull style
f (g x) --
( f . g ) (x) --
|
// c
f(g(x))
|
pętle
- Control.Monad.Loops (whileM_)[9]
- go
go
Funkcja go[10]
-- https://stackoverflow.com/questions/5926033/haskell-efficient-equivalent-of-for-loop
import System.IO
loop :: Int -> IO ()
loop n = go n
where
go n | n <= 0 = return ()
go n = go (n-1)
main = loop 1000000
-- https://gist.github.com/niorad/45187d9eb76c585e573e
divideBy x y = go x y 0
where go a b count
| a < b = (count, a)
| otherwise = go (a - b) b (count + 1)
Zmienna count jest pomocniczym licznikiem
Listy
Listy skończone [11]
sum [1..10]
product [1..10]
Listy nieskończone (przykład leniwego wartościowania): [12]
[1,3..] [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,{Interrupted!}
take 20 [1,3..] [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39]
cycle
Cycle
ghci> take 10 (cycle [1,2,3]) -- weź 10 pierwszych elementów z listy cyklicznej utworzonej przez powtarzanie elementów listy [1,2,3]
[1,2,3,1,2,3,1,2,3,1]
ghci> take 12 (cycle "LOL ")
"LOL LOL LOL "
Klasy
Monady
Poradniki:
Wejście i wyjście
Wczytywanie argumentów:
-- http://zvon.org/other/haskell/Outputsystem/getArgs_f.html -- save it as a file a.hs -- runhaskell a.hs 1 33 aaaa import System main = do x <- getArgs print x
Wczytywanie pliku tekstowego, którego nazwa jest podana jako argument programu:
-- save it as a file f.hs -- runhaskell f.hs gruff.txt import System main = do args <- System.getArgs let fileName = head args print fileName -- read text file text <- readFile fileName -- putStrLn text
Pliki z kodem w Haskellu
hs
Pliki z rozszerzeniem hs zawierają kod Haskella. Może to być:[13]
- funkcja
- moduł
- pakiet
- program
Funkcje
Definicję funkcji mojafunkcja zapisz do pliku mojafunkcja.hs W trybie interaktywnym ( ghci) wczytujesz funkcję za pomocą komendy:
:l mojafunkcja
albo
:r -- reload current script
Moduł
Moduł zawiera kilka funkcji. Każdy moduł to jeden plik. Nazwa modułu odpowiada nazwie pliku, z wyjątkiem modułu głównego.
Standardowe moduły:
- Prelude[14]
Sprawdzmy listę funkcji w module :
:browse nazwa_modułu
Pakiet
Pakiet zawsze zawiera: [15]
- jeden lub kilka modułów
Może zawierać:
- kod w języku C
- pliki nagłówkowe
- dokumentację
- testy dla zawartych modułów
- dodatkowe narzędzia
Polecenie:
ghc-pkg list
pokazuje listę zainstalowanych pakietów [16]
Możemy poprosić o opis jednego z zainstalowanych modułów, np time:
ghc-pkg describe time
Cabal
Cabal jest to program ułatwiający pracę z pakietami.
Pakiety cabala mogą występować w 3 postaciach:
- kodu źródłowego (skompresowanego w plikach tar-ball, zip)
- plikach binarnych
- specjalnych postaciach: RPM, pakiety Debiana, windows [17]
Przykład :
ghc-pkg Vector -- sprawdzamy czy mamy moduł vector cabal update -- uaktualniamy cabal cabal install Vector -- instalujemy moduł vector
Program
Kompletny program w Haskellu zawiera jeden lub więcej modułów (w tym główny moduł Main) skompilowanych z użyciem pakietów (w tym pakiet Prelude)
Pierwszy program
Najprostszy program składa się z:[18][19]
- jednego głównego pakietu (main)
- jednego głównego modułu (Main)
- jednej głównej funkcji (main). [20][21]
-- moduł główny Main module Main (main) -- nazwa eksportowanej funkcji where -- definicja funkcji main main = putStrLn "Hello world"
Program zapisujemy do pliku, np. w.hs
Jak widać nazwa pliku zawierającego moduł główny nie musi być taka sama jak nazwa modułu.
Program kompilujemy:
ghc -o w w.hs
i uruchomiamy:
./w
Bardziej skomplikowany przykład, trójkąt Sierpińskiego:
-- http://dev.stephendiehl.com/hask/#diagrams
import Diagrams.Prelude
import Diagrams.Backend.SVG.CmdLine
sierpinski :: Int -> Diagram SVG
sierpinski 1 = eqTriangle 1
sierpinski n =
s
===
(s ||| s) # centerX
where
s = sierpinski (n - 1)
example :: Diagram SVG
example = sierpinski 5 # fc black
main :: IO ()
main = defaultMain example
Uruchamiamy:
runhaskell diagram1.hs -w 256 -h 256 -o diagram1.svg
Pierwszy projekt
Projekt [22]
hsl
Pliki z rozszerzeniem hsl zawierają kod w stylu programowania piśmiennego (ang. literate programming) [23]
Jak pracować w Haskellu
- tryb interaktywny (ghci)
- kompilacja kodu (ghc)
- z użyciem skryptu runhaskell
runhaskell
Z użyciem skryptu BASHA:
runhaskell m.hs
ghc
W trybie kompilacji najpierw kompilujemy:
ghc -o m m.hs
potem uruchamiamy wykonywalny plik:
./m
Sprawdzamy wersję i zainstalowane moduły:
ghc -v
przykładowy wynik :
Glasgow Haskell Compiler, Version 7.10.3, stage 2 booted by GHC version 7.10.3 Using binary package database: /usr/lib/ghc/package.conf.d/package.cache wired-in package ghc-prim mapped to ghc-prim-0.4.0.0-6cdc86811872333585fa98756aa7c51e wired-in package integer-gmp mapped to integer-gmp-1.0.0.0-3c8c40657a9870f5c33be17496806d8d wired-in package base mapped to base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d wired-in package rts mapped to builtin_rts wired-in package template-haskell mapped to template-haskell-2.10.0.0-3c4cb52230f347282af9b2817f013181 wired-in package ghc mapped to ghc-7.10.3-624693c6aa854116c707bc7b4d0d7cb6 wired-in package dph-seq not found. wired-in package dph-par not found. Hsc static flags: *** Deleting temp files: Deleting: *** Deleting temp dirs: Deleting: ghc: no input files Usage: For basic information, try the `--help' option.
Dostępne moduły :
ghc-pkg list
przykładowy wynik :
/usr/lib/ghc/package.conf.d Cabal-1.22.5.0 array-0.5.1.0 base-4.8.2.0 bin-package-db-0.0.0.0 binary-0.7.5.0 bytestring-0.10.6.0 containers-0.5.6.2 deepseq-1.4.1.1 directory-1.2.2.0 filepath-1.4.0.0 ghc-7.10.3 ghc-prim-0.4.0.0 haskeline-0.7.2.1 hoopl-3.10.0.2 hpc-0.6.0.2 integer-gmp-1.0.0.0 pretty-1.1.2.0 process-1.2.3.0 rts-1.0 template-haskell-2.10.0.0 terminfo-0.4.0.1 time-1.5.0.1 transformers-0.4.2.0 unix-2.7.1.0 xhtml-3000.2.1
ghci
W trybie interaktywnym:
ghci m.hs
potem uruchamiamy funkcję:
main
Ładowanie (wczytanie) modułów:
:load nazwa
Po wczytaniu modułu trzeba go uaktywnić:
:module nazwa
np.:
:m + Fractal.RUFF.Mandelbrot.Address
uaktywnia moduł Address z pakietu RUFF (m jest skrótem od module [24])
:quit
aby wyjść
Tryb edycji wieloliniowej (ang. multiline-input mode )
:set +m
Problemy
cabal: unrecognised command: sandbox (try --help)
Może wersja cabala jest za stara?[25] Sprawdzamy:
cabal -V
przykładowy wynik:
cabal-install version 1.16.0.2 using version 1.16.0 of the Cabal library
upgrade:
cabal install cabal-install
oraz:
export PATH="$HOME/.cabal/bin:${PATH}"
Pomoc
info
:info name
przykład:
:info ($)
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’
infixr 0 $
path
:show paths
zmień ścieżkę:
:cd path
typ
:t nazwa
hlint
hlint a.hs
Zobacz również
- How to read Haskell code ?
- Understanding Basic Haskell Error Messages by Jan Stolarek
- Marcin Szlenk - programowanie w języku Haskell i funkcyjne
- Haskell - Tomek „QsoRiX” Rydzynski
- Programowanie funkcyjne - Marcin Kubica
- Haskell Cheat Sheet
- haskell operatorer
- Learn you a Haskell - In a nutshell by Michael Härtl
- stackoverflow question: getting-started-with-haskell
- wyszukiwarki:
Odnośniki
- ↑ EPIGRAMS IN PROGRAMMING
- ↑ Teoria kategorii
- ↑ Paradygmaty_programowania : Małgorzata Moczurad i Włodzimierz Moczurad — Uniwersytet Jagielloński
- ↑ David Mertz - Haskell tutorial
- ↑ Pointfree style
- ↑ stackoverflow question : how-to-define-a-function-in-ghci-across-multiple-lines
- ↑ Gracjan Polak - Instalacja GHC w wersji minimalnej
- ↑ Podobne Beginning with the Haskell Programming Language by gnosis
- ↑ avoiding writing recursive functions by refactoring by Franklin Chen
- ↑ stackoverflow question: haskell-why-the-convention-to-name-a-helper-function-go
- ↑ Programowanie w Haskellu - Artur Zawłocki
- ↑ "Strumienie, czyli pochwała lenistwa" artykuł Marcina Benke, Delta, lipiec 2013
- ↑ stackoverflow question: whats-the-difference-between-module-package-and-library-in-haskell
- ↑ Moduł Prelude
- ↑ System pakietów Haskella
- ↑ Pakiety Haslkella
- ↑ Pakiety w Haskellu
- ↑ Pakiety w Haskellu
- ↑ stackoverflow question: iin-need-of-the-most-simple-haskell-program
- ↑ Pliki z kodem źródłowym w ang podręczniku
- ↑ Aplikacja Haskella w ang wikibooks
- ↑ Struktura pierwszego projeltu w Haskellu
- ↑ Programowanie piśmienne w wikipedii
- ↑ Using GHCi doc
- ↑ Stackoverflow question: cabal-run-gives-unrecognised-command-run