FP / Jazyk Lambda

Jazyk λ

Funkcionálne programovanie

Čo to je?

Motivácia

Entscheidungs­problem

Formálna definícia algoritmu

  1. Kurt Gödel
    Čiastočne rekurzívne funkcie (1933)
  2. Alonzo Church
    λ kalkul (1936)
  3. Alan Turing
    Turingov stroj (1936)

Všetky sú ekvivalentné — Churchova–Turingova téza

Turingov stroj

$$ {\displaystyle M=\langle Q,\Gamma ,b,\Sigma ,\delta ,q_{0},F\rangle } $$

Alebo radšej vizuálne

Hierarchia výpočtových modelov

Výraz λ


expression ::= name                     variable
            |  expression expression    application
            |  λ name . expression      abstraction
            |  ( expression )           grouping

Aplikácia

Abstrakcia

Haskell

Automatický currying

add :: Int -> Int -> Int
add x y = x + y

-- Je v skutočnosti:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)

Premenné

Transformácie

  1. Zámena alfa (α) — premenovanie premennej
    λa.a b $\leftrightarrow$ λy.y b
  2. Zámena beta (β) — „dosadenie“
    (λa.a b) f $\leftrightarrow$ f b
  3. Zámena eta (η) — zjednodušenie
    (λa.f a) $\leftrightarrow$ f

Iba pre viazané premenné. Voľné premenné musia zostať voľnými.

Konflikt mien

(λa.λb.a b) b c $\rightarrow^\beta$ (λb.b b) c — nesprávne

(λa.λb.a b) b c
$\rightarrow^\alpha$ (λa.λx.a x) b c
$\rightarrow^\beta$ (λx.b x) c
$\rightarrow^\beta$ b c

Redukcia

(λa.λb.a b) (λc.c) d
$\rightarrow^\beta$ (λb.(λc.c) b) d
$\rightarrow^\beta$ (λc.c) d
$\rightarrow^\beta$ d

Eta redukcia v praxi

Eta redukcia: (λa.f a) $\leftrightarrow$ f

double x = 2 * x
double = (2 *)          -- point-free (eta redukcia)

sum xs = foldl (+) 0 xs
sum = foldl (+) 0       -- point-free

A čo hodnoty?

Iba funkcie!

Church encoding

True & False

if then else

Operátory

Kombinátory

Kombinátor — abstrakcia lambda bez voľných premenných.

K I(λa.λb.a) (λa.a)λb.(λa.a)λa.(λb.b)KI

Boolovské operácie pomocou kombinátorov

Pozrime sa na to inák

data Bool = True | False

not :: Bool -> Bool
not True  = False
not False = True
type CBool = forall a. a -> a -> a

cTrue :: CBool
cTrue = \ifTrue ifFalse -> ifTrue

cFalse :: CBool  
cFalse = \ifTrue ifFalse -> ifFalse

cNot :: CBool -> CBool
cNot p = p cFalse cTrue

Čísla

Čísla

0 = false

Ďalšie čísla

succ 2
$M\equiv$ (λn.λf.λx.f (n f x)) (λf.λx.f (f x))
$\rightarrow^\alpha$ (λn.λf.λx.f (n f x)) (λa.λb.a (a b))
$\rightarrow^\beta$ λf.λx.f ((λa.λb.a (a b)) f x)
$\rightarrow^\beta$ λf.λx.f ((λb.f (f b)) x)
$\rightarrow^\beta$ λf.λx.f (f (f x)) = 3

Operátory

Ďalší kombinátor

Dvojica

type CPoint = forall r. (Double -> Double -> r) -> r

cPoint :: Double -> Double -> CPoint
cPoint x y = \f -> f x y

movePoint :: CPoint -> Double -> Double -> CPoint
movePoint p dx dy = p (\x y -> cPoint (x + dx) (y + dy))
type CShape = forall r. (CPoint -> Double -> r)  -- Circle
                      -> (CPoint -> CPoint -> r) -- Rectangle
                      -> r
cCircle :: CPoint -> Double -> CShape
cCircle c r = \fCircle fRectangle -> fCircle c r

cRectangle :: CPoint -> CPoint -> CShape
cRectangle p1 p2 = \fCircle fRectangle -> fRectangle p1 p2  
cArea :: CShape -> Double
cArea shape = shape areaCircle areaRectangle
    where
        areaCircle :: CPoint -> Double -> Double
        areaCircle center radius = pi * radius^2
        areaRectangle :: CPoint -> CPoint -> Double
        areaRectangle p1 p2 = 
            p1 (\x1 y1 -> 
            p2 (\x2 y2 -> abs((x2 - x1) * (y2 - y1))))

Pattern matching

Algebraický dátový typ

data List a = Nil | Cons a (List a)

-- Pattern matching:
length :: List a -> Int
length Nil = 0                    -- prvá vetva
length (Cons x xs) = 1 + length xs -- druhá vetva
type CList a = forall r. r -> (a -> r -> r) -> r

cNil :: CList a
cNil = \nil cons -> nil

cCons :: a -> CList a -> CList a
cCons x xs = \nil cons -> cons x (xs nil cons)

cLength :: CList a -> Int
cLength list = list 0 (\x rec -> 1 + rec)

Rekurzia?

Faktoriál

Faktoriál

Y combinator

Y = (λh.(λx.h (x x)) (λx.h (x x)))

Y g = … = g (Y g)

Haskell

import Data.Function (fix)

fact = fix (\f n -> if n == 0 then 1 else n * f (n-1))

Kombinátory

Kombinátory

S K I

Všetky funkcie je možné vyjadriť pomocou troch kombinátorov:

Alebo dokonca dvoch, lebo I = S K K

Haskell

GHC

Iné jazyky