FP / Typové triedy a polymorfizmus

Typové triedy
a polymorfizmus

Funkcionálne programovanie

Skôr než začneme

Hľadanie indexu v štandardnej knižnici

elemIndex       :: Eq a => a -> [a] -> Maybe Int
elemIndex x      = findIndex (x==)
findIndex       :: (a -> Bool) -> [a] -> Maybe Int
findIndex p      = listToMaybe . findIndices p
findIndices     :: (a -> Bool) -> [a] -> [Int]
findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]

Pokračovanie

listToMaybe :: [a] -> Maybe a
listToMaybe = foldr (const . Just) Nothing
const      :: a -> b -> a
const x _  =  x

Pokračovanie

listToMaybe :: [a] -> Maybe a
listToMaybe = foldr (\x acc -> (const . Just) x acc) Nothing
const      :: a -> b -> a
const x _  =  x

Pokračovanie

listToMaybe :: [a] -> Maybe a
listToMaybe = foldr (\x acc -> (const (Just x) acc) Nothing
const      :: a -> b -> a
const x _  =  x

Pokračovanie

listToMaybe :: [a] -> Maybe a
listToMaybe = foldr (const . Just) Nothing
const      :: a -> b -> a
const x _  =  x

Polymorfizmus

Typy polymorfizmu

Príklady

Ad-hoc polymorfizmus

Prekrývanie funkcií a operátorov

int times(int x, int y) {
    return x * y;
}
String times(int n, String s) {
    return StringUtils.repeat(s, n);
}

Parametrický polymorfizmus

Typové parametre

Polymorfizmus podtypov

Podtypy

Liskov substitution principle

Subtype Requirement: Let ⁠$\phi(x)$⁠ be a property provable about objects ⁠$x$⁠ of type T. Then ⁠$\phi(y)$⁠ should be true for objects ⁠$y⁠$ of type S where S is a subtype of T.

Liskov, Barbara; Wing, Jeannette (1994-11-01). “A behavioral notion of subtyping”. ACM Transactions on Programming Languages and Systems. 16 (6): 1811–41. doi:10.1145/197320.197383

Inheritance ≠ subtyping

Haskell?

Haskell

Typové triedy

Typové triedy

class Show a where
    show :: a -> String

instance Show Bool where
    show True  = "True"
    show False = "False"
class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool

instance Eq Point where 
    (Point x1 y1) == (Point x2 y2)  =  x1 == x2 && y1 == y2
    a /= b  =  not (a == b)

Predvolená implementácia

class Eq a where
    (==), (/=) :: a -> a -> Bool
    x /= y  =  not (x == y)
    x == y  =  not (x /= y)

Príklad

elem :: ?
elem x []     = False
elem x (y:ys) = x==y || (elem x ys)

Typ?

elem :: a -> [a] -> Bool
elem x []     = False
elem x (y:ys) = x==y || (elem x ys)

Kontext

elem :: (Eq a) => a -> [a] -> Bool
elem x []     = False
elem x (y:ys) = x==y || (elem x ys)

Kontext inštancie

instance Eq a => Eq (List a) where
    Nil == Nil              =  True
    Cons x xs == Cons y ys  =  x == y && xs == ys
    _ == _                  =  False

Dedičnosť

class (Eq a) => Ord a where
    compare              :: a -> a -> Ordering 
    (<), (<=), (>=), (>) :: a -> a -> Bool
    max, min             :: a -> a -> a

Haskell vs Java

Nie elem :: Eq -> [Eq] -> Bool,
ale elem :: (Eq a) => a -> [a] -> Bool

Implementácia inštancie

Štandartné typové triedy pre čísla

Ďalšie štandartné typové triedy

Typové triedy vyššieho rádu

class Functor f where
    fmap :: (a -> b) -> f a -> f b
instance Functor List where
  fmap op Nil       = Nil
  fmap op (Cons x xs) = Cons (op x) (fmap op xs)

Druhy (kinds)

Functor

class Functor f where
    fmap :: (a -> b) -> f a -> f b
instance Functor List where
  fmap op Nil       = Nil
  fmap op (Cons x xs) = Cons (op x) (fmap op xs)

Ďalšie typové triedy

elem v skutočnosti

class Foldable t where
    ...
    elem :: Eq a => a -> t a -> Bool
    elem = any . (==)
    ...
elem x xs = any (\y -> y == x) xs
elem x = any (\y -> y == x)
elem x = any (==x)
elem x = any ((==) x)
elem x = (any . (==)) x
elem = any . (==)

Automatické odvodenie

data Shape = Circle Point Double
           | Rectangle Point Point
           deriving (Eq, Ord, Show)

Niekde inde?

Rust

trait Show {
    fn show(&self) -> String;
}

impl Show for bool {
    fn show(&self) -> String {
        if *self { "true" } else { "false" }.to_string()
    }
}

A tiež

Typy v jazyku Haskell