Haskell – Moduły

Transkrypt

Haskell – Moduły
Haskell – Moduły
Moduł – zestaw powiązanych funkcji, typów, typeclass.
Program w Haskellu często jest modułem, który ładuje
inne moduły a następnie wykorzystuje zdefiniowane w
nich funkcje w celu realizacji postawionego zadania.
Haskell dostarcza w postaci modułów bibliotekę funkcji
pozwalających np. na: operacje na liczbach zespolonych,
operacje na listach, programowanie współbieżne itp.
Domyślnie importowany jest moduł Prelude, z którego
dotychczas korzystaliśmy.
Haskell – Moduły – Ładowanie
Załadowanie modułu:
import <nazwa modułu>
np.:
import Data.List
Od tego momentu exportowane przez Data.List funkcje
itp. są dostępne. Np.:
import Data.List
numUniques :: (Eq a) => [a] ­> Int
numUniques = length . nub
Haskell – Moduły – Ładowanie
Używając ghci można załadować moduł poprzez:
ghci > :m + Data.List
Można również załadować jednocześnie wiele modułów:
ghci > :m + Data.List Data.Map Data.Set
Funkcje eksportowane przez załadowane w ten sposób
moduły dostępne są w globalnej przestrzeni nazw tzn.
można się do nich odwoływać przez ich nazwy.
Haskell – Moduły – Ładowanie
W przypadku potrzeby użycia tylko kilku
eksportowanych przez moduł możn użyć formy:
z
funkcji
import Data.List (nub, sort)
Spowoduje to, że funkcji nub i sort z modułu Data.List będą
dostępne w globalnej przestrzeni nazw. Inną możliwością
jest użycie wszystkich funkcji modułu z wyjątkiem
wymienionych:
import Data.List hiding (nub)
W tym przypadku funkcja nub nie będzie dostępna w
globalnej przestrzeni nazw.
Haskell – Moduły – Ładowanie
Użycie formy:
import qualified Data.Map
Spowoduje, że użycie funkcji eksportowanej przez moduł
będzie wymagało wyspecyfikowanie nazwy kwalifikowanej np.:
Data.Map.filter
Użycie konstrukcji:
import qualified Data.Map as M
daje możliwość skrócenia zapisu do:
M.filter
Haskell – Moduły
Przydatne moduły:
Data.List – operacje na listach
Data.Char – operacje na znakach
Data.Map – operacje na tablicach asocjacyjnych
Data.Set – operacje na zbiorach
Haskell – Moduły - Pomoc
Aby wyświetlić listę funkcji eksportowanych przez moduł:
Prelude> :browse Data.List
Można również zastosować:
Prelude> :m +Data.List
Prelude Data.List> Data.List.<TAB>
Display all 112 possibilities? (y or n)
Data.List.!! Data.List.foldr1 Data.List.mapAccumR Data.List.tails
Data.List.++ Data.List.genericDrop Data.List.maximum Data.List.take
Data.List.\\ Data.List.genericIndex Data.List.maximumBy Data.List.takeWhile
Haskell – Moduł – Data.List
Przykładowe funkcje;
transpose – transpozycja listy list
ghci > transpose [[1,2,3],[4,5,6],
[7,8,9]]
[[1,4,7],[2,5,8],[3,6,9]]
ghci > transpose ["hey","there","guys"]
["htg","ehu","yey","rs","e"]
Haskell – Moduł – Data.List
concat – zamiany listy list na listę
ghci > concat ["foo","bar","car"]
"foobarcar"
ghci > concat [[3,4,5],[2,3,4],
[2,1,1]]
[3,4,5,2,3,4,2,1,1]
Haskell – Moduł – Data.List
and – przyjmuje listę wartości logicznych jako
argument i zwraca True jeśli wszystkie wartości na
liście mają wartość True
ghci > and $ map (>4) [5,6,7,8]
True
ghci > and $ map (==4) [4,4,4,3,4]
False
Podobnie działa or.
Haskell – Moduł – Data.List
Zamiast or i and w połączniu z map można użyć odpowiednio any i
all:
ghci > any (==4) [2,3,5,6,1,4]
True
ghci > all (>4) [6,9,10]
True
ghci > all (`elem ` ['A'..'Z']) "HEYGUYSwhatsup"
False
ghci > any (`elem ` ['A'..'Z']) "HEYGUYSwhatsup"
True
Haskell – Moduł – Data.List
iterate przyjmuje jako argument funkcję i wartość
startową a następnie przykłada funkcję do wartości
startowej po czym do wyniku przykłada funkcję, po czym
do wyniku przykłada funkcję itd. Wszystkie wyniki zwraca
jako listę nieskończoną:
ghci > take 10 $ iterate (*2) 1
[1,2,4,8,16,32,64,128,256,512]
ghci > take 3 $ iterate (++ "haha") "haha"
["haha","hahahaha","hahahahahaha"]
Haskell – Moduł – Data.List
sort – sortuje listę elementów typeclass Ord:
ghci > sort [8,5,3,2,1,6,4,2]
[1,2,2,3,4,5,6,8]
ghci > sort "This will be sorted soon"
" Tbdeehiillnooorssstw"
Haskell – Moduł – Data.List
words dzieli linię tekstu na słowa a unwords tworzy linię tekstu z listy słów:
ghci > words "hey these are the words in this sentence"
["hey","these","are","the","words","in","this","sentenc
e"]
ghci > words "hey these are the words in this\nsentence"
["hey","these","are","the","words","in","this","sentenc
e"]
ghci > unwords ["hey","there","mate"]
"hey there mate"
Haskell – Moduł – Data.List
nub usuwa z listy duplikaty elementów listy:
ghci > nub [1,2,3,4,3,2,1,2,3,4,3,2,1]
[1,2,3,4]
ghci > nub "Lots of words and stuff"
"Lots fwrdanu"
Haskell – Moduł – Data.Char
Moduł Data.Char zawiera funkcje do operowania na
pojedynczych znakach np.:
IsAlphaNum zwraca True jeśli argument jest znakiem
alfanumerycznym lub False w przeciwnym przypadku:
ghci > all isAlphaNum "bobby283"
True
ghci > all isAlphaNum "eddy the fish!"
False
Haskell – Moduł – Data.Char
Data.Char dostarcza m.in. funkcje toUpper i toLower a
także digitToInt i intToDigit:
ghci > map digitToInt "34538"
[3,4,5,3,8]
ghci > map digitToInt "FF85AB"
[15,15,8,5,10,11]
ghci > intToDigit 15
'f'
ghci > intToDigit 5
'5'
Haskell – Moduł – Data.Map
Moduł Data.Map dostarcza funkcji do przeprowadzania operacji na
tablicach asocjacyjnych. Tablice asocjacyjne mogą być reprezentowane
jako lista krotek:
phoneBook =
[("betty","555­2938")
,("bonnie","452­2928")
,("patsy","493­2928")
,("lucille","205­2928")
,("wendy","939­8282")
,("penny","853­2492")
]
Haskell – Moduł – Data.Map
W module Data.Map używany jest typ Map.
Zmienne tego typu można utworzyć np.:
Prelude M> let lista = M.fromList [("Zed", 10), ("Ted", 5)] Prelude M> :t lista
lista :: M.Map [Char] Integer
Haskell – Moduł – Data.Map
empty zwraca pustą mapę
insert przyjmuje jako parametr klucz, wartość i
mapę i zwraca nową mapę z wstawionym kluczem i
wartością:
ghci > Map.empty
fromList []
ghci > Map.insert 3 100 Map.empty
fromList [(3,100)]
Haskell – Moduł – Data.Map
lookup przyjmuje jako argument klucz i listę i zwraca Just wartość jeżeli
dla klucza istnieje wartość lub Nothing jeżeli nie znajdzie klucza.
Prelude M> M.lookup "Ted" lista
Just 5
member jako argumenty przyjmuje klucz i mapę i zwraca informację czy
dla klucza istnieje wartość:
ghci > Map.member 3 $ Map.fromList [(3,6),(4,3),(6,9)]
True
ghci > Map.member 3 $ Map.fromList [(2,5),(4,5)]
False
Haskell – Moduł – Data.Set
Moduł Data.Set oferuje operacje na zbiorach. Zbiory
podobnie jak mapy tworzone są z list np.:
Prelude> import qualified Data.Set as Set
Prelude Set> let setA = Set.fromList [ 1, 2, 3]
Prelude Set> let setB = Set.fromList [ 3, 4, 5]
Prelude Set> :t setA
setA :: Set.Set Integer
Haskell – Moduł – Data.Set
Na zbiorach możliwe są typowe dla zbiorów operacje jak
intersection, difference:
Prelude Set> Set.intersection setA setB
fromList [3]
Prelude Set> Set.difference setA setB
FromList [1,2]
Prelude Set> Set.union setA setB
fromList [1,2,3,4,5]
Haskell – Moduły – Tworzenie
Aby utworzyć własny moduł np. zawierajacy funkcje
zwiazane z geometrią należy utworzyć plik .hs (np.:
Geometry.hs) zawierający nagłowek opisujący jakie
funkcje moduł eksportuje (udostępnia):
module Geometry
( sphereVolume
, sphereArea
, cubeVolume
) where
Haskell – Moduły – Tworzenie
Po czym następują definicje funkcji np.:
sphereVolume :: Float ­> Float
sphereVolume radius = (4.0 / 3.0) * pi * (radius ^ 3)
sphereArea :: Float ­> Float
sphereArea radius = 4 * pi * (radius ^ 2)
Haskell – Moduły – Tworzenie
Własnego modułu można użyć tak jak modułów
dostarczanych standardowo:
ghci> import Geometry
Haskell – Moduły – Tworzenie
Moduły mogą być tworzone jako konstrukcje
hierarchiczne. Każdy moduł może zawierać
podmoduły. Moduł Geometry może zostać
przedstawiony jako zawierający podmoduły dla
różnych rodzajów obiektów.
Należy utworzyć katalog Geometry zawierający
pliki sphere.hs, cuboid.hs and cube.hs.
Haskell – Moduły – Tworzenie
sphere.hs
module Geometry.Sphere
( volume
, area
) where
volume :: Float ­> Float
volume radius = (4.0 / 3.0) * pi * (radius ^ 3)
area :: Float ­> Float
area radius = 4 * pi * (radius ^ 2)
Haskell – Moduły – Tworzenie
cuboid.hs
module Geometry.Cuboid
( volume
, area
) where
volume :: Float ­> Float ­> Float ­> Float
volume a b c = rectangleArea a b * c
area :: Float ­> Float ­> Float ­> Float
area a b c = rectangleArea a b * 2 + rectangleArea a c * 2 + rectangleArea c
b * 2
rectangleArea :: Float ­> Float ­> Float
rectangleArea a b = a * b
Haskell – Moduły – Tworzenie
cube.hs
module Geometry.Cube
( volume
, area
) where
import qualified Geometry.Cuboid as Cuboid
volume :: Float ­> Float
volume side = Cuboid.volume side side side
area :: Float ­> Float
area side = Cuboid.area side side side
Haskell – Moduły – Tworzenie
Użycie takiego modułu:
import Geometry.Sphere
Teraz można użyć area i volume do wyliczenia pola i objętości
kuli. Można również wykonać:
import qualified Geometry.Sphere as Sphere
import qualified Geometry.Cuboid as Cuboid
import qualified Geometry.Cube as Cube
Można wtedy wywołać: Sphere.area, Sphere.volume itd. do
obliczenia pola powierzchni i objętości odpowiednich obiektów.

Podobne dokumenty