TU Wien:Funktionale Programmierung VU (Knoop)/Prüfung 2021-05-28 (Lösungsvorschlag)

Aus VoWi
Zur Navigation springen Zur Suche springen

Aufgabe 1[Bearbeiten | Quelltext bearbeiten]

1. Zwei Nat-Werte und sind gleich gdw. die Anzahl der Succ vor Null gleich ist.

2. Ein Nat-Wert ist echt größer als ein Nat-Wert gdw. die Anzahl der Succ vor Null größer ist.

Aufgabe 2[Bearbeiten | Quelltext bearbeiten]

module Prüfung where
import Data.List

data Nat = Null | Succ Nat deriving (Eq,Ord)

plus :: Nat -> Nat -> Nat 
plus Null y = y 
plus (Succ x) y = Succ (plus x y) -- recursively adds succs from x to y

minus :: Nat -> Nat -> Nat 
minus x y
 | x < y = Null
 | x == y = Null

minus (Succ x) (Succ y) = minus x y -- recursively removes succs
minus x (Null) = x

mal :: Nat -> Nat -> Nat 
mal (Succ x) y = (plus y (mal x y)) -- recursively adds y for x times
mal (Null) y = Null

type Quotient = Nat 
type Rest = Nat 
data QR = QR Quotient Rest deriving Show

durch :: Nat -> Nat -> QR 
durch x (Null) = error "division by Zero" 
durch x y
 | x < y = QR Null x 
 | x == y = QR (Succ Null) Null 
durch x y = (plusQR (QR (Succ Null) Null) (durch (minus x y) y)) 
-- checks if x bigger then y and adds 1 to quotient result. In case x smaller, returns x as rest

plusQR :: QR -> QR -> QR 
plusQR (QR x y) (QR z f) = QR (plus x z) (plus y f) --helper function to sum results

Aufgabe 3[Bearbeiten | Quelltext bearbeiten]

1. Es gibt keine Werte die nicht als Resultat vorkommen könnten. Daher wäre jeder Rückgabewert außer einem Programmabbruch verschleiernd.

2. Da der Ergebnistyp geändert werden darf, könnte ein Wert hinzugefügt werden, der bei normaler Ausführung nicht benötigt wird.


Aufgabe 4[Bearbeiten | Quelltext bearbeiten]

instance Show Nat where
  show (Succ (Succ (Succ (Succ (Succ (Succ x)))))) = "++++ " ++ show (Succ x)
  show (Succ (Succ (Succ (Succ (Succ Null))))) = "++++"
  show (Succ x) = "|" ++ show x
  show (Null) = ""

Wenn mehr als 5 Succ dann ++++ mit Space
Wenn genau 5 Succ dann ++++
Wenn mindestens ein Succ dann |
Wenn null dann fertig ... das ganze rekursiv


Andere Meinung: Der Fall show Null ist hier nicht abgedeckt. Dazu würde es dann eine Abänderung an der Logik brauchen. Ich habe das ganze so implementiert:

instance Show Nat where
  show Null = "Null"
  show (Succ (Succ (Succ (Succ (Succ Null))))) = "++++"
  show (Succ (Succ (Succ (Succ (Succ a))))) = "++++ " ++ show a
  show (Succ Null) = "|"
  show (Succ x) = "|" ++ show x

Aufgabe 5[Bearbeiten | Quelltext bearbeiten]

--f :: (Integer, Integer) -> Integer

fhelp :: Integer -> Integer -> Integer -> Integer 
fhelp z zs current
 | current <= z || (z <= 0) && (current <= (z*(-1))) = (current ^ zs) + (fhelp z zs (current +1))
 | otherwise = 0

fmap :: Integer -> Integer -> Integer 
fmap x y
 | x<=0 = sum (map (^y) [0..(x*(-1))])
 | otherwise = sum (map (^y) [0..x])


ffold :: Integer -> Integer -> Integer 
ffold x y
 | x<=0 = foldl (+) 0 (map (^y) [0..(x*(-1))])
 | otherwise = foldl (+) 0 (map (^y) [0..x])

Anderer Lösungsvorschlag

-- mit direkt rekursiver Hilfsfunktion helper
f_1 :: (Integer, Integer) -> Integer
f_1 (x, y) = helper [0..(abs x)] (abs y)

helper :: [Integer] -> Integer -> Integer
helper [] _ = 0
helper (l:ls) y = l^y + helper ls y

-- Listenkomprehension und sum
f_2 :: (Integer, Integer) -> Integer
f_2 (x,y) = sum [z^(abs y) | z <- [0..(abs x)]]

-- Listenkomprehension und fold
f_3 :: (Integer, Integer) -> Integer
f_3 (x,y) = foldl (+) 0 [z^(abs y) | z <- [0..(abs x)]]

Aufgabe 6[Bearbeiten | Quelltext bearbeiten]

Allgemeinster Typ von k:

k :: ((a,b,c) -> d) -> a -> b -> c -> d

1. Klammerungen

-- a
k :: ((a,b,c) -> d) -> a -> b -> c -> d

-- b
k :: (((a,b,c) -> d) -> (a -> (b -> (c -> d))))


2. Der allgemeinste Typ ist paramterisch / echt / uneingeschränkt polymorph.

3.

-- (i)
(f(x,y,z))

-- (ii)
((((k f) x) y) z)

4.

5.

k (\(x,y,z) -> x*y+z) (2+3) (3*5) (7-5)

-- linksnormal (Argumente unausgewertet übergeben)

(E) ->> (2+3)*(3*5)+(7-5)
(S) ->> 5*(3*5)+(7-5)
(S) ->> 5*15+(7-5)
(S) ->> 75+(7-5)
(S) ->> 75+2
(S) ->> 77

-- linksapplikativ (Argumente ausrechnen und dann expandieren)

(S) ->> (\(x,y,z) -> x*y+z) 5 (3*5) (7-5)
(S) ->> (\(x,y,z) -> x*y+z) 5 15 (7-5)
(S) ->> (\(x,y,z) -> x*y+z) 5 15 2
(E) ->> 5*15+2
(S) ->> 75+2
(S) ->> 77

6.

k ist eine Funktion die eine Funktion und ihre Parameter erhält und die übergebenen Parameter in ein Tupel zusammenfasst. Somit ist sie ähnlich zur Funktion curry (lediglich mit mehr Parametern) siehe Vergleich der Typsignaturen:

Prelude> :t k
k :: ((a, b, c) -> d) -> a -> b -> c -> d

Prelude> :t curry
curry :: ((a,b) -> c) -> a -> b -> c