Úvod do síťové komunikace, pole v Haskellu
IB016 Seminář z funkcionálního programování
Vladimír Štill, Martin Ukrop
Fakulta informatiky, Masarykova univerzita
Jaro 2016
IB016: Cvičení 08 Jaro 2016 1 / 15
Síťová komunikace v Haskellu (HTTP)
Existuje mnoho různých balíků, které se liší
podporovanými schopnostmi (autentizace, šifrování,
komprese, ...)
závislostmi (třeba zlib je často vyžadováno kvůli kompresi)
úrovní dokumentace
IB016: Cvičení 08 Jaro 2016 2 / 15
Modul Network.HTTP
Asi nejjednodušší je balík HTTP
základní HTTP funkcionalita obsažena v modulu
Network.HTTP
umožňuje provádět HTTP dotazy a dostávat odpovědi
umí pracovat s proxy, autentizací připojení, cookies, ...
neumí šifrování, kompresi dat, ...
pracuje v monádě IO (jednoduché dotazy), nebo
BrowserAction (více dotazů v rámci jednoho sezení)
IB016: Cvičení 08 Jaro 2016 3 / 15
Network.HTTP – základní funkce
simpleHTTP :: HStream ty =>
Request ty -> IO (Result (Response ty))
otevře přímé jednorázové spojení na zadaný server
zašle normalizovaný dotaz a vrátí odpověď
getRequest :: String -> Request_String
ze zadaného URL vytvoří GET dotaz
getResponseBody :: Result (Response ty) -> IO ty
getResponseCode ::
Result (Response ty) -> IO ResponseCode
vrátí tělo/kód z výsledku HTTP dotazu
IB016: Cvičení 08 Jaro 2016 4 / 15
Network.HTTP – příklad
> simpleHTTP (getRequest "http://www.haskell.org/")
>>= getResponseBody
"\n
302 Found\n
\n
302 Found
\n
nginx/1.6.2\n
\n
\n"
IB016: Cvičení 08 Jaro 2016 5 / 15
Práce s URL
balík network-uri pro práci s URL
modul Network.URI
parseURI :: String -> Maybe URI
URI je záznam umožňující přístup k jednotlivým částem
převod zpět na String pomocí show
interakce s Network.HTTP:
v modulu Network.HTTP.Base (exportováno i z
Network.HTTP)
defaultGETRequest :: URI -> Request_String
defaultGETRequest_ :: BufferType a => URI ->
Request a
typová třída BufferType je předkem HStream
IB016: Cvičení 08 Jaro 2016 6 / 15
Cabal sandboxy
Motivace
někdy chceme balíky z Hackage jen vyzkoušet
odinstalace je obtížná
můžeme mít různé verze závislostí v různých projektech
to vše způsobuje v klasické instalaci v cabalu problémy
IB016: Cvičení 08 Jaro 2016 7 / 15
Cabal sandboxy
Motivace
někdy chceme balíky z Hackage jen vyzkoušet
odinstalace je obtížná
můžeme mít různé verze závislostí v různých projektech
to vše způsobuje v klasické instalaci v cabalu problémy
Sandboxy (cabal ≥ 1.18)
umožňuje vytvořit lokální instalaci balíčků ve složce
cabal sandbox init – inicializuje sandbox v aktuální složce
následné cabal install BALÍK probíhá do sandboxu
binárky v ./.cabal-sandbox/bin
ghc standardně nedokáže detekovat sandbox samo
→ cabal repl spustí ghci v sandboxu (cabal ≥ 1.19)
cabal sandbox delete
IB016: Cvičení 08 Jaro 2016 7 / 15
Pole v Haskellu
Proč zavádět datový typ pole? Jaké má vlastnosti?
IB016: Cvičení 08 Jaro 2016 8 / 15
Pole v Haskellu
Proč zavádět datový typ pole? Jaké má vlastnosti?
struktura mapující indexy na hodnoty
struktura s konstantním náhodným přístupem
časté náhodné čtení je efektivní
čistá datová struktura (pure), takže při změně prvku musíme
celé pole vybudovat znova
balík array, modul Data.Array
IB016: Cvičení 08 Jaro 2016 8 / 15
Typová třída Ix
class Ord a => Ix a where
range :: (a,a) -> [a]
index :: (a,a) -> a -> Int
inRange :: (a,a) -> a -> Bool
typy, které můžou sloužit jako index
knihovní instance pro Int, Integer, Char, Bool, uspořádané
n-tice, . . .
instance pro výčtové typy možno automaticky odvodit
IB016: Cvičení 08 Jaro 2016 9 / 15
Konstrukce pole I.
array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
zkonstruuje pole z asociativního seznamu a hranic indexů
asociativní seznam musí obsahovat každý index nejvýše jednou
opakovaný index nebo index mimo meze způsobí vytvoření
nedefinovaného pole
nezmíněné indexy nejsou definované
IB016: Cvičení 08 Jaro 2016 10 / 15
Konstrukce pole I.
array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
zkonstruuje pole z asociativního seznamu a hranic indexů
asociativní seznam musí obsahovat každý index nejvýše jednou
opakovaný index nebo index mimo meze způsobí vytvoření
nedefinovaného pole
nezmíněné indexy nejsou definované
squares = array (1,100) [(i, i*i) | i <- [1..100]]
IB016: Cvičení 08 Jaro 2016 10 / 15
Práce s polem
(!) :: Ix i => Array i e -> i -> e
bounds :: Ix i => Array i e -> (i, i)
elems :: Ix i => Array i e -> [e]
range :: Ix a => (a, a) -> [a]
assocs :: Ix i => Array i e -> [(i, e)]
IB016: Cvičení 08 Jaro 2016 11 / 15
Konstrukce pole II.
mkArray :: (Ix a) => (a -> b) -> (a,a) -> Array a b
mkArray f bs = array bs [(i, f i) | i <- range bs]
konstrukce pole zadáním funkce na indexech
funkce může používat předešlé hodnoty pole
IB016: Cvičení 08 Jaro 2016 12 / 15
Konstrukce pole II.
mkArray :: (Ix a) => (a -> b) -> (a,a) -> Array a b
mkArray f bs = array bs [(i, f i) | i <- range bs]
konstrukce pole zadáním funkce na indexech
funkce může používat předešlé hodnoty pole
mkArray (\i -> i * i) (1,100)
fibs :: Int -> Array Int Int
fibs n = a
where a = array (0,n) ([(0, 1), (1, 1)] ++
[(i, a!(i-2) + a!(i-1)) | i <- [2..n]])
IB016: Cvičení 08 Jaro 2016 12 / 15
Úpravy pole
(//) :: (Ix a) => Array a b -> [(a,b)] -> Array a b
accum :: Ix i =>
(e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
Pozor, konstruujeme nové pole!
IB016: Cvičení 08 Jaro 2016 13 / 15
Úpravy pole
(//) :: (Ix a) => Array a b -> [(a,b)] -> Array a b
accum :: Ix i =>
(e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
Pozor, konstruujeme nové pole!
m // [((i,i), 0) | i <- [1..n]]
swapRows :: (Ix a, Ix b, Enum b) =>
a -> a -> Array (a,b) c -> Array (a,b) c
swapRows i i' ar = ar //
([((i ,j), ar!(i',j)) | j <- [jLo..jHi]] ++
[((i',j), ar!(i ,j)) | j <- [jLo..jHi]])
where ((iLo,jLo),(iHi,jHi)) = bounds ar
IB016: Cvičení 08 Jaro 2016 13 / 15
Jiné typy polí v Haskellu
Immutable IO monad ST monad
Standard Array
DiffArray
IOArray STArray
Unboxed UArray
DiffUArray
IOUArray,
StorableArray
STUArray
Array (klasické neměnitelné pole)
IOArray (měnitelné pole v monáde IO)
STArray (měnitelné pole v monáde ST)
DiffArray (hybridní model: měnitelné pole s rozhraním jako
neměnitelné pole)
Je to celé ještě složitější, více na wiki.haskell.org/Arrays
IB016: Cvičení 08 Jaro 2016 14 / 15
Samostatný úkol
Naprogramujte sadu základních funkcí pro práci s maticemi
uložených v datové struktuře (neměnitelného) pole. Pro inspiraci
můžete použít typové signatury níže.
type Matrix = Array (Int,Int) Int
identity :: Int -> Matrix
square :: Matrix -> Bool
identical :: Matrix -> Matrix -> Bool
add :: Matrix -> Matrix -> Matrix
trace :: Matrix -> [Int]
transpose :: Matrix -> Matrix
conformable :: Matrix -> Matrix -> Bool
multiply :: Matrix -> Matrix -> Matrix
inversePair :: Matrix -> Matrix -> Bool
IB016: Cvičení 08 Jaro 2016 15 / 15