Órai forráskód

--- 1. gyakorlat
-----

f(1) = A
f(2) = B
f(3) = C

------


f(1) = A
f(2) = A
f(3) = B

------

f(1) = A
f(1) = B
f(2) = C

------

1
2
1 + 2
(1 + 2) * 100 = 300

-------------


Melyik NEM függvény és miért?

f(x) = 1
f(z) = 2

g(X) = true
g(Y) = false
g(X) = false

h(1) = "hello"
h(3) = "world"
h(2) = "Haskell"

--- 2. gyakorlat
-----

-- masodik.hs
-- Windows parancsori értelmezők
-- powershell
-- cmd

-- Fájlok listázása: ls VAGY dir

-- ghci spéci parancsok
-- :l masodik.hs <- betöltés   (load)
-- :r            <- újratöltés (reload)
s = "Haskell is cool"

-- https://people.inf.elte.hu/poor_a/

inc n = n + 1

even' m = m `mod` 2 == 0

even'' m = mod m 2 == 0

-- Összehasonlító operátorok (függvények):
--   2 == 2  egyenlő
--   2 /= 3  nem egyenlő
--   2 >  1  nagyobb
--   2 >= 2  nagyobb vagy egyenlő


--  logikai operátorok (függvények):
--  True && True      logikai ÉS
--  True || False     logikai VAGY

-- Logikai ÉS művelet
-- True  ÉS True  -> True
-- True  ÉS False -> False
-- False ÉS True  -> False
-- False ÉS False -> False

-- Mintaillesztés:
and' True True = True
and' True False = False
and' False True = False
and' False False = False

and'' True True = True
and'' _    _    = False


--- 3. gyakorlat
-----
xor True True = False
xor True False = True
xor False True = True
xor False False = False

xor''''' False a = a
xor''''' True  a = not a

xor' a b = a /= b


{-
xor'' True False = True -- parciális függvény
xor'' False True = True
-}

xor'' True False = True -- totális függvény
xor'' False True = True
xor'' a     b    = False

{-
-- Nem jó, mert minden paraméternek különböző nevet kell adni
xor''' True False = True
xor''' False True = True
xor''' a     a    = False
-}

xor'''' True False = True -- totális függvény
xor'''' False True = True
xor'''' _     _    = False -- catch all minta: _

{-
xor'''' _     _    = False
xor'''' True False = True -- totális függvény
xor'''' False True = True
-}

------

-- Karakter minták

isA 'a' = True
isA 'A' = True
isA _ = False


-----------


fugven 42 12

a fugven z -> mod a z \= 0 -- rossz
fugven a z = mod a z /= 0  -- helyes
a `fugven` z =

--- 4. gyakorlat
-----

fun 'a' = "is"
fun 'x' = "interesting"
fun 'y' = "functional"
fun _   = "Haskell"

-----

Kérdések:

"Haskell"   "is"      "functional"

Parciális vagy totális? Miért?

-----

-- downloads.haskell.org

nextDay a
  | a < 0 = error "nextDay: input can't be negative"
  | a > 6 = error "nextDay: input can't be greater than 6"
  | a == 6 = 0
  | otherwise = a + 1  -- otherwise nem kötelező, helyette szerepelhetne a < 6 is (mert már csak az maradt ki)

-- ez is ugyanolyan jó:
nextDay a
  | a == 6 = 0
  | 0 <= a && a < 6 = a + 1
  | a < 0 = error "nextDay: input can't be negative"
  | a > 6 = error "nextDay: input can't be greater than 6"

--- Rekurzió

-- Nem jó:
-- fact :: Integer -> Integer
-- fact n = n * fact (n-1)       -- Rekurzív eset

-- Végtelen rekurzió:
-- Hiányzik a nem rekurzív alapeset
-- fact 2 -> 2 * fact 1 -> 2 * 1 * fact 0 -> 2 * 1 * 0 * fact (-1) ...

fact :: Integer -> Integer
fact 0 = 1                    -- Alapeset (nem rekurzív függvényág)
fact n = n * fact (n-1)       -- Rekurzív eset

--- 5. gyakorlat
-----

min' x y
  | x <= y  =  x
  | x >  y  =  y


------

min'' x y
  | x <= y  = x   -- ha elfogytak az őrfeltételek (mindegyik False volt), akkor megyünk a következő függvényágra
min'' x y         -- azaz ide
  | x > y   = y

--- 6. gyakorlat
-----

descending :: Int -> [Int]
descending n = list
  where                     -- segédváltozók és segédfüggvények
    list = [n, n-1 .. (-n)]

data Something = SomeInt Int | SomeString String -- új saját adatszerkezet

--- 7. gyakorlat
-----

ghci> import Data.Char
ghci>
ghci>
ghci> [ c | c <- "Hello World", isUpper c]
"HW"
ghci> [ toLower c | c <- "Hello World", isUpper c]
"hw"
ghci> [ toLower c | c <- "Hello World", isUpper c, c elem ['a'..'g']]
""
ghci> [ toLower c | c <- "Hello World", isUpper c, c elem ['A'..'G']]
""
ghci> [ toLower c | c <- "Hello World", isUpper c, c elem ['A'..'H']]
"h"

--- 8. gyakorlat
-----

x^2 + 4x + 6      // x = 42
42^2 + 4*42 + 6

head :: [a] -> a      // a = Int
head :: [Int] -> Int

zip :: [a] -> [b] -> [(a,b)] // a = Int, b = String
zip :: [Int] -> [String] -> [(Int, String)]


Ugyanazt jelenti a kettő minta listákon:
myMinimum [x] = x
myMinimum (x : []) = x

--- 9. gyakorlat
-----

infixr 3 +:+
(+:+) :: [a] -> [a] -> [a]
[]     +:+ bs = bs
(a:as) +:+ bs = a : (as +:+ bs)

myConcat as bs = as +:+ bs

second (x, y) = y

--- 10. gyakorlat
-----

data Point = Coordinates Int Int
  deriving (Eq, Ord)

-- Coordinates :: Int -> Int -> Point

-- ghci-ben
-- :t Coordinates
-- Coordinates :: Int -> Int -> Point
--
-- :i Eq

data TrafficLight = Red | Yellow | Green
  deriving Show

--  data Int = ... | -3 | -2 | -1 | 0 | 1 | 2 | 3 ...

showPoint :: Point -> String
showPoint (Coordinates x y) = "(" ++ show x ++ ", " ++ show y ++ ")"

instance Show Point where
  -- show :: Point -> String
  show (Coordinates x y) = "(" ++ show x ++ ", " ++ show y ++ ")"


data MaybeInt = NothingInt | JustInt Int
  deriving (Eq, Show)

showMaybeInt :: MaybeInt -> String
showMaybeInt NothingInt  = "Itt nincs semmi"
showMaybeInt (JustInt n) = "Itt van egy szam: " ++ show n

data MaybeDouble = NothingDouble | JustDouble Double
  deriving (Eq, Show)

data MaybeString = NothingString | JustString String
  deriving (Eq, Show)

-- data Maybe a = Nothing | Just a
--            ^ típusparaméter
--

-------------

ghci> import Data.Maybe
ghci>
ghci>
ghci> listToMaybe [1,2,3]
Just 1
ghci> listToMaybe []
Nothing
ghci> listToMaybe "Haskell"
Just 'H'
ghci> :t listToMaybe "Haskell"
listToMaybe "Haskell" :: Maybe Char
ghci> :t listToMaybe ""
listToMaybe "" :: Maybe Char
ghci> listToMaybe ""
Nothing
ghci> listToMaybe [True, False]
Just True
ghci> :t listToMaybe [True, False]
listToMaybe [True, False] :: Maybe Bool

-------------

--- 11. gyakorlat
-----

map f [x1,   x2,     x3 ...   xn] ==
      [f x1, f x2, f x3 ... f xn]

ghci> map (+1) [1,2,3]
[2,3,4]
ghci> import Data.Char
ghci> map toUpper "haskell"
"HASKELL"
ghci> :t map
map :: (a -> b) -> [a] -> [b]
ghci> isUpper 'H'
True
ghci> isUpper 'h'
False
ghci> filter isUpper "Hello World"
"HW"
ghci> :t map
map :: (a -> b) -> [a] -> [b]
ghci> map length ["haskell", "is", "cool"]
[7,2,4]
ghci> map (filter isUpper) ["Haskell", "Is", "cOOl"]
["H","I","OO"]
ghci> filterUpper s = filter isUpper s
ghci> filterUpper "Haskell"
"H"
ghci> map filterUpper ["Haskell", "Is", "cOOl"]
["H","I","OO"]
ghci> :t filter
filter :: (a -> Bool) -> [a] -> [a]
ghci> filterChar c = isUpper c && c `elem` ['a'..'k']
ghci> filterChar 'a'
False
ghci> filterChar 'x'
False
ghci> filterChar 'A'
False
ghci> filterChar c = isUpper c && c `elem` ['A'..'K']
ghci> filterChar 'A'
True
ghci> filterChar 'K'
True
ghci> filterChar 'P'
False
ghci> filterChar c = isUpper c || c == ' '
ghci> filterChar 'P'
True
ghci> filterChar c = c `elem` ['A'..'K'] || c == ' '
ghci> filterChar 'P'
False
ghci> filterChar 'A'
True
ghci> filterChar ' '
True
ghci> filterChar 'a'
False
ghci> filter filterChar "Haskell"
"H"
ghci> filter filterChar "HaskeLL"
"H"
ghci> filter filterChar "HaskeLL is Functional"
"H  F"
ghci> filter isUpper "Haskell"
"H"
ghci> filter isUpper "HaskeLL"
"HLL"
ghci> filter isLower (filter isUpper "HaskeLL")
""
ghci> filter (\n -> n > 2 && n < 5) [1,9,0,20,42,4,3,4,5]
[4,3,4]
ghci> (\n -> n > 2 && n < 5) 2
False
ghci> (\n -> n > 2 && n < 5) 3
True
ghci> (\n -> n > 2 && n < 5) 4
True
ghci> :t (\n -> n > 2 && n < 5)
(\n -> n > 2 && n < 5) :: (Ord a, Num a) => a -> Bool
ghci> between2and5 = (\n -> n > 2 && n < 5)
ghci> between2and5 3
True
ghci> between2and5 4
True
ghci> between2and5 5
False

-- Identitás függvény:
-- (\x -> x) -- Haskell
-- λx.x      -- Lambda kalkulus

--

data Adat = Szemely String Int
  deriving Show

data Person = NewHuman {
    nev :: String,
    szuletesiEv :: Int,
    varos :: String
} deriving Show


--- 12. gyakorlat
-----

Függvénykompozíció is egy (magasabb rendű) függvény Haskellben:
(.) :: (b -> c) -> (a -> b) -> a -> c

Típus levezetése:

f     ::      b -> c
g     :: a -> b
f . g :: a      -> c

eltűnik a köztes 'b' típusú érték

reverse (dropSpaces (reverse (dropSpaces "   Hello    Haskell     ")))

(reverse . dropSpaces . reverse . dropSpaces) "   Hello    Haskell     "


Részeredmény felbontása függvényen belül kisebb komponensekre:

myGroup list = ...
  where
    (first, rest) = span (...) list


--- 13. gyakorlat
-----

data Brand = Ford | Suzuki | Volkswagen
  deriving (Show, Eq, Ord, Enum)

data Car = Automobile Brand Int String
  deriving (Show)

myCar :: Car
myCar = Automobile Volkswagen 5 "FKJ-245"

neighborsCar :: Car
neighborsCar = Automobile Suzuki 5 "ABC-123"

isVolkswagen :: Car -> Bool
isVolkswagen (Automobile brand doors license) = brand == Volkswagen

{-
isVolkswagen :: Car -> Bool
isVolkswagen (Automobile Volkswagen doors license) = True
isVolkswagen _ = False
-}

-------------

ghci> :{
ghci| isDivisible :: Int -> Int -> Bool
ghci| isDivisible a b = a `mod` b == 0
ghci| :}
ghci> isDivisible 10 2
True
ghci> isDivisible 10 3
False
ghci> :t isDivisible
isDivisible :: Int -> Int -> Bool
ghci> :t isDivisible 10
isDivisible 10 :: Int -> Bool
ghci> :t filter
filter :: (a -> Bool) -> [a] -> [a]
ghci> filter (isDivisible 10) [2,3,4,1,10,200,300,5]
[2,1,10,5]
ghci> words " Hello Haskell"
["Hello","Haskell"]

-------------

data TreeType = Birch | Oak | Beech | Maple deriving (Eq, Show)

data Tree = Alive TreeType Age
          | Dead TreeType Age
          deriving (Eq, Show)

type Age = Integer

updateTreeAge :: Tree -> Tree
updateTreeAge (Alive typ age) = Alive typ (age + 1)
updateTreeAge (Dead typ age) = Dead typ age

{-
updateTreeAge :: Tree -> Tree
updateTreeAge (Alive typ age) = Alive typ (age + 1)
updateTreeAge tree = tree
-}

updateTreeAges :: [Tree] -> [Tree]
updateTreeAges trees = map updateTreeAge trees