initial commit
This commit is contained in:
commit
9ba103928d
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
dist
|
||||||
|
dist-*
|
||||||
|
cabal-dev
|
||||||
|
*.o
|
||||||
|
*.hi
|
||||||
|
*.chi
|
||||||
|
*.chs.h
|
||||||
|
*.dyn_o
|
||||||
|
*.dyn_hi
|
||||||
|
.hpc
|
||||||
|
.hsenv
|
||||||
|
.cabal-sandbox/
|
||||||
|
cabal.sandbox.config
|
||||||
|
*.prof
|
||||||
|
*.aux
|
||||||
|
*.hp
|
||||||
|
*.eventlog
|
||||||
|
.stack-work/
|
||||||
|
cabal.project.local
|
||||||
|
*~
|
41
.travis.yml
Normal file
41
.travis.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# This is the simple Travis configuration, which is intended for use
|
||||||
|
# on applications which do not require cross-platform and
|
||||||
|
# multiple-GHC-version support. For more information and other
|
||||||
|
# options, see:
|
||||||
|
#
|
||||||
|
# https://docs.haskellstack.org/en/stable/travis_ci/
|
||||||
|
#
|
||||||
|
# Copy these contents into the root directory of your Github project in a file
|
||||||
|
# named .travis.yml
|
||||||
|
|
||||||
|
# Use new container infrastructure to enable caching
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
# Do not choose a language; we provide our own build tools.
|
||||||
|
language: generic
|
||||||
|
|
||||||
|
# Caching so the next build will be fast too.
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.stack
|
||||||
|
|
||||||
|
# Ensure necessary system libraries are present
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libgmp-dev
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
# Download and unpack the stack executable
|
||||||
|
- mkdir -p ~/.local/bin
|
||||||
|
- export PATH=$HOME/.local/bin:$PATH
|
||||||
|
- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Build dependencies
|
||||||
|
- stack --no-terminal --install-ghc test --only-dependencies
|
||||||
|
|
||||||
|
script:
|
||||||
|
# Build the package, its tests, and its docs and run the tests
|
||||||
|
- stack --no-terminal test --haddock --no-haddock-deps
|
||||||
|
|
30
LICENSE
Normal file
30
LICENSE
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Copyright Author name here (c) 2017
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Author name here nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
111
README.md
Normal file
111
README.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
Übungszettel 1
|
||||||
|
==============
|
||||||
|
|
||||||
|
Dieses Repository dient der ersten Übung des Moduls Fortgeschrittene
|
||||||
|
Funktionale Programmierung in Haskell.
|
||||||
|
Wir werden sowohl in den Übungen als auch für das Projekt als Compiler den GHC
|
||||||
|
in Version >= 8 verwenden, sowie stack, ein Progamm zur Unterstützung der
|
||||||
|
Entwicklung von Haskell programmen.
|
||||||
|
|
||||||
|
Als Editor/IDE empfehlen wir nvim.
|
||||||
|
|
||||||
|
|
||||||
|
Stack
|
||||||
|
-----
|
||||||
|
> $ stack update
|
||||||
|
|
||||||
|
Neuste Paketliste laden
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack setup
|
||||||
|
|
||||||
|
Läd den GHC und andere erforderliche Daten für ein das Projekt herunter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack build
|
||||||
|
|
||||||
|
Baut das Projekt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack test
|
||||||
|
|
||||||
|
Testet das Projekt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack haddock
|
||||||
|
|
||||||
|
Generiert die Dokumentation für das Projekt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack ghci
|
||||||
|
|
||||||
|
Compiliert das Projekt und startet den GHCi im Kontext des Projekts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> $ stack help
|
||||||
|
|
||||||
|
Try for yourself
|
||||||
|
|
||||||
|
|
||||||
|
Github
|
||||||
|
------
|
||||||
|
|
||||||
|
Wir verwenden Github statt des Lernraums/LernraumPLUS/moodle/etc.
|
||||||
|
Das bedeutet, dass ihr einen Github-Account braucht.
|
||||||
|
|
||||||
|
Das hoch und runterladen der Aufgaben / des Projekts erfolgt mit dem
|
||||||
|
Kommandozeilenprogramm git.
|
||||||
|
|
||||||
|
> $ git clone https://github.com/[..]
|
||||||
|
|
||||||
|
Klont ein git-repository in eine extra dafür neu angelegten Ordner
|
||||||
|
|
||||||
|
> $ git status
|
||||||
|
|
||||||
|
Zeigt den status des git-repository's an. Das bedeutet, welche Dateien
|
||||||
|
verändert wurden, und welche Änderungen "staged for commit" sind, dh. in einen
|
||||||
|
Commit einfließen werden.
|
||||||
|
|
||||||
|
> $ git commit -am "Aufgabe1.hs solved"
|
||||||
|
|
||||||
|
Speichert alle Änderungen, die staged sind, in einen Commit mit einer Commit
|
||||||
|
Message.
|
||||||
|
|
||||||
|
> $ git push
|
||||||
|
|
||||||
|
Pusht die Commits, dh. läd alle Commits hoch.
|
||||||
|
|
||||||
|
Falls ihr nvim verwendet, gibt es im Editor einige Plugins für eine direkte
|
||||||
|
Integration von git.
|
||||||
|
|
||||||
|
Github Classroom
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Ihr werdet einen Link an eure Github-Mail erhalten, welcher euch Zugang einem
|
||||||
|
Assignment gibt.
|
||||||
|
|
||||||
|
Jedes Assignment erstellt ein neues privaten Repository mit der
|
||||||
|
Aufgabenstellung, in welches ihr eure Lösungen hochladen könnt.
|
||||||
|
|
||||||
|
|
||||||
|
Travis CI
|
||||||
|
---------
|
||||||
|
|
||||||
|
Travis ist ein continuous integration service. Immer wenn ihr eine Aufgabe
|
||||||
|
bearbeitet habt und diese auf Github pusht, läd Travis diesen push in eine
|
||||||
|
virtuelle Maschiene und baut und testet die neue Version.
|
||||||
|
|
||||||
|
Das bedeutet folgendes:
|
||||||
|
- Ihr bekommt direkt Feedback zu euren Lösungen
|
||||||
|
- Wir bekommen eine Mail wenn ein Build fehlschlägt/fehlerfrei durchläuft
|
||||||
|
- Ihr habt ein Konsolen-Log, in dem Ihr einezelne Zeilen makieren könnt und
|
||||||
|
anschließend den Link an uns weiterleiten könnt um genaue Erklärungen
|
||||||
|
bzw. Lösungshilfen zu Fehlern zu bekommen
|
||||||
|
|
||||||
|
Mit anderen Worten, ihr müsst nicht im Tutorium sitzen um effizient mit euren
|
||||||
|
Tutoren zu kommunizieren
|
6
app/Aufgabe1Main.hs
Normal file
6
app/Aufgabe1Main.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Aufgabe1
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn result
|
6
app/Aufgabe2Main.hs
Normal file
6
app/Aufgabe2Main.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Aufgabe2
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn result
|
6
app/Aufgabe3Main.hs
Normal file
6
app/Aufgabe3Main.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Aufgabe3
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn result
|
6
app/Aufgabe4Main.hs
Normal file
6
app/Aufgabe4Main.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Aufgabe4
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn result
|
48
src/Aufgabe1.hs
Normal file
48
src/Aufgabe1.hs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{-
|
||||||
|
Aufgabe 1
|
||||||
|
=========
|
||||||
|
-}
|
||||||
|
module Aufgabe1 where
|
||||||
|
|
||||||
|
|
||||||
|
{- Gegeben ist der Datentyp Pred a, der eine Prüffunktion (Prädikat) repräsentiert,
|
||||||
|
die einen Wert vom Typ a zu einem Wert vom Typ Bool auswertet.
|
||||||
|
Beachten Sie, dass mit dem Wertekonstruktor Pred bereits eine Funktion
|
||||||
|
Pred :: (a -> Bool) -> Pred a
|
||||||
|
gegeben ist, mit der Sie ein Prädikat "einpacken" können.
|
||||||
|
-}
|
||||||
|
|
||||||
|
newtype Pred a = Pred (a -> Bool)
|
||||||
|
|
||||||
|
{- Schreiben Sie eine Funktion unPred, die das Prädikat "auspackt".
|
||||||
|
-}
|
||||||
|
|
||||||
|
unPred :: Pred a -> (a -> Bool)
|
||||||
|
unPred = undefined
|
||||||
|
|
||||||
|
{- Da Haskell-Funktionen grundsätzlich “gecurried” sind, bzw. der (->)-Operator
|
||||||
|
rechtsassoziativ ist, können Sie die Klammern hinten in der Signatur auch weglassen
|
||||||
|
und erhalten unPred :: Pred a -> a -> Bool, was man zugleich als “wende Pred a an,
|
||||||
|
wenn du ein a bekommst” lesen kann.
|
||||||
|
-}
|
||||||
|
|
||||||
|
{- Definieren Sie nun eine Funktion isVowel, die prüft, ob ein Buchstabe ein Vokal ist.
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
isVowel :: Pred Char
|
||||||
|
isVowel = undefined
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
Schreiben Sie eine Funktion filterVowels, die alle Vorkommen von Vokalen aus
|
||||||
|
einem String entfernt. Verwenden Sie hierfür das Prädikat isVowel.
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
filterVowels :: String -> String
|
||||||
|
filterVowels = undefined
|
||||||
|
|
||||||
|
|
||||||
|
result :: String
|
||||||
|
result = filterVowels "Hello World!"
|
47
src/Aufgabe1.lhs
Normal file
47
src/Aufgabe1.lhs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Aufgabe 1
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe1 where
|
||||||
|
|
||||||
|
|
||||||
|
Gegeben ist der Datentyp Pred a, der eine Prüffunktion (Prädikat) repräsentiert,
|
||||||
|
die einen Wert vom Typ a zu einem Wert vom Typ Bool auswertet.
|
||||||
|
Beachten Sie, dass mit dem Wertekonstruktor Pred bereits eine Funktion
|
||||||
|
Pred :: (a -> Bool) -> Pred a
|
||||||
|
gegeben ist, mit der Sie ein Prädikat "einpacken" können.
|
||||||
|
|
||||||
|
> newtype Pred a = Pred (a -> Bool)
|
||||||
|
|
||||||
|
Schreiben Sie eine Funktion unPred, die das Prädikat "auspackt".
|
||||||
|
|
||||||
|
|
||||||
|
> unPred :: Pred a -> (a -> Bool)
|
||||||
|
>
|
||||||
|
> unPred = undefined
|
||||||
|
|
||||||
|
Da Haskell-Funktionen grundsätzlich “gecurried” sind, bzw. der (->)-Operator
|
||||||
|
rechtsassoziativ ist, können Sie die Klammern hinten in der Signatur auch weglassen
|
||||||
|
und erhalten unPred :: Pred a -> a -> Bool, was man zugleich als “wende Pred a an,
|
||||||
|
wenn du ein a bekommst” lesen kann.
|
||||||
|
|
||||||
|
|
||||||
|
Definieren Sie nun eine Funktion isVowel, die prüft, ob ein Buchstabe ein Vokal ist.
|
||||||
|
|
||||||
|
|
||||||
|
> isVowel :: Pred Char
|
||||||
|
>
|
||||||
|
> isVowel = undefined
|
||||||
|
|
||||||
|
|
||||||
|
Schreiben Sie eine Funktion filterVowels, die alle Vorkommen von Vokalen aus
|
||||||
|
einem String entfernt. Verwenden Sie hierfür das Prädikat isVowel.
|
||||||
|
|
||||||
|
|
||||||
|
> filterVowels :: String -> String
|
||||||
|
>
|
||||||
|
> filterVowels = undefined
|
||||||
|
|
||||||
|
|
||||||
|
> result :: String
|
||||||
|
>
|
||||||
|
> result = filterVowels "Hello World!"
|
47
src/Aufgabe1.md
Normal file
47
src/Aufgabe1.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Aufgabe 1
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe1 where
|
||||||
|
|
||||||
|
|
||||||
|
Gegeben ist der Datentyp Pred a, der eine Prüffunktion (Prädikat) repräsentiert,
|
||||||
|
die einen Wert vom Typ a zu einem Wert vom Typ Bool auswertet.
|
||||||
|
Beachten Sie, dass mit dem Wertekonstruktor Pred bereits eine Funktion
|
||||||
|
Pred :: (a -> Bool) -> Pred a
|
||||||
|
gegeben ist, mit der Sie ein Prädikat "einpacken" können.
|
||||||
|
|
||||||
|
> newtype Pred a = Pred (a -> Bool)
|
||||||
|
|
||||||
|
Schreiben Sie eine Funktion unPred, die das Prädikat "auspackt".
|
||||||
|
|
||||||
|
|
||||||
|
> unPred :: Pred a -> (a -> Bool)
|
||||||
|
>
|
||||||
|
> unPred = undefined
|
||||||
|
|
||||||
|
Da Haskell-Funktionen grundsätzlich “gecurried” sind, bzw. der (->)-Operator
|
||||||
|
rechtsassoziativ ist, können Sie die Klammern hinten in der Signatur auch weglassen
|
||||||
|
und erhalten unPred :: Pred a -> a -> Bool, was man zugleich als “wende Pred a an,
|
||||||
|
wenn du ein a bekommst” lesen kann.
|
||||||
|
|
||||||
|
|
||||||
|
Definieren Sie nun eine Funktion isVowel, die prüft, ob ein Buchstabe ein Vokal ist.
|
||||||
|
|
||||||
|
|
||||||
|
> isVowel :: Pred Char
|
||||||
|
>
|
||||||
|
> isVowel = undefined
|
||||||
|
|
||||||
|
|
||||||
|
Schreiben Sie eine Funktion filterVowels, die alle Vorkommen von Vokalen aus
|
||||||
|
einem String entfernt. Verwenden Sie hierfür das Prädikat isVowel.
|
||||||
|
|
||||||
|
|
||||||
|
> filterVowels :: String -> String
|
||||||
|
>
|
||||||
|
> filterVowels = undefined
|
||||||
|
|
||||||
|
|
||||||
|
> result :: String
|
||||||
|
>
|
||||||
|
> result = filterVowels "Hello World!"
|
41
src/Aufgabe2.hs
Normal file
41
src/Aufgabe2.hs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
-- Aufgabe 2
|
||||||
|
-- =========
|
||||||
|
|
||||||
|
module Aufgabe2 where
|
||||||
|
|
||||||
|
-- Machen Sie sich mit den Modulen
|
||||||
|
|
||||||
|
import List
|
||||||
|
|
||||||
|
import ERPSys
|
||||||
|
|
||||||
|
-- vertraut. Einige der Aufgaben diese Woche basieren auf diesen.
|
||||||
|
|
||||||
|
-- Hypothetisches Real-World Problem
|
||||||
|
-- ---------------------------------
|
||||||
|
|
||||||
|
-- Gegeben ein bereits existierendes Warenwirtschaftssystem (Modul ERPSys), welches
|
||||||
|
-- auf einer eigenen Datenstruktur (Modul List) basiert.
|
||||||
|
|
||||||
|
-- Die Firma, in der Sie arbeiten wird beauftragt, ein neues Kassensystem zu
|
||||||
|
-- entwickeln. Sie werden beauftragt, den Scanalogorithmus der Kasse zu
|
||||||
|
-- programmieren.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Dazu ist zuerst die Funktion `findArticle` zu entwickeln, die gegeben einen
|
||||||
|
-- Barcode und eine Produktliste einen Artikel findet.
|
||||||
|
|
||||||
|
findArticle :: (Eq a) => a -> ProductList a b c -> Maybe (Article a b c)
|
||||||
|
|
||||||
|
findArticle = undefined
|
||||||
|
|
||||||
|
productCatalog :: ProductList Int String Float
|
||||||
|
productCatalog = insert (Article 1 "Apfel" 1)
|
||||||
|
$ insert (Article 2 "Birne" 0.5)
|
||||||
|
$ insert (Article 3 "Banane" 1.5)
|
||||||
|
$ insert (Article 4 "Tomate" 0.75)
|
||||||
|
ListEnd
|
||||||
|
|
||||||
|
|
||||||
|
result = show $ findArticle 2 productCatalog
|
41
src/Aufgabe2.lhs
Normal file
41
src/Aufgabe2.lhs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Aufgabe 2
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe2 where
|
||||||
|
|
||||||
|
Machen Sie sich mit den Modulen
|
||||||
|
|
||||||
|
> import List
|
||||||
|
>
|
||||||
|
> import ERPSys
|
||||||
|
|
||||||
|
vertraut. Einige der Aufgaben diese Woche basieren auf diesen.
|
||||||
|
|
||||||
|
Hypothetisches Real-World Problem
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Gegeben ein bereits existierendes Warenwirtschaftssystem (Modul `ERPSys`), welches
|
||||||
|
auf einer eigenen Datenstruktur (Modul `List`) basiert.
|
||||||
|
|
||||||
|
Die Firma, in der Sie arbeiten wird beauftragt, ein neues Kassensystem zu
|
||||||
|
entwickeln. Sie werden beauftragt, eine Teil des Scanalogorithmuses der Kasse zu
|
||||||
|
programmieren.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dazu ist zuerst die Funktion `findArticle` zu entwickeln, die gegeben einen
|
||||||
|
Barcode und eine Produktliste einen Artikel findet.
|
||||||
|
|
||||||
|
> findArticle :: (Eq a) => a -> ProductList a b c -> Maybe (Article a b c)
|
||||||
|
>
|
||||||
|
> findArticle = undefined
|
||||||
|
|
||||||
|
> productCatalog :: ProductList Int String Float
|
||||||
|
> productCatalog = insert (Article 1 "Apfel" 1)
|
||||||
|
> $ insert (Article 2 "Birne" 0.5)
|
||||||
|
> $ insert (Article 3 "Banane" 1.5)
|
||||||
|
> $ insert (Article 4 "Tomate" 0.75)
|
||||||
|
> ListEnd
|
||||||
|
|
||||||
|
|
||||||
|
> result = show $ findArticle 2 productCatalog
|
41
src/Aufgabe2.md
Normal file
41
src/Aufgabe2.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Aufgabe 2
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe2 where
|
||||||
|
|
||||||
|
Machen Sie sich mit den Modulen
|
||||||
|
|
||||||
|
> import List
|
||||||
|
>
|
||||||
|
> import ERPSys
|
||||||
|
|
||||||
|
vertraut. Einige der Aufgaben diese Woche basieren auf diesen.
|
||||||
|
|
||||||
|
Hypothetisches Real-World Problem
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Gegeben ein bereits existierendes Warenwirtschaftssystem (Modul `ERPSys`), welches
|
||||||
|
auf einer eigenen Datenstruktur (Modul `List`) basiert.
|
||||||
|
|
||||||
|
Die Firma, in der Sie arbeiten wird beauftragt, ein neues Kassensystem zu
|
||||||
|
entwickeln. Sie werden beauftragt, eine Teil des Scanalogorithmuses der Kasse zu
|
||||||
|
programmieren.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dazu ist zuerst die Funktion `findArticle` zu entwickeln, die gegeben einen
|
||||||
|
Barcode und eine Produktliste einen Artikel findet.
|
||||||
|
|
||||||
|
> findArticle :: (Eq a) => a -> ProductList a b c -> Maybe (Article a b c)
|
||||||
|
>
|
||||||
|
> findArticle = undefined
|
||||||
|
|
||||||
|
> productCatalog :: ProductList Int String Float
|
||||||
|
> productCatalog = insert (Article 1 "Apfel" 1)
|
||||||
|
> $ insert (Article 2 "Birne" 0.5)
|
||||||
|
> $ insert (Article 3 "Banane" 1.5)
|
||||||
|
> $ insert (Article 4 "Tomate" 0.75)
|
||||||
|
> ListEnd
|
||||||
|
|
||||||
|
|
||||||
|
> result = show $ findArticle 2 productCatalog
|
31
src/Aufgabe3.hs
Normal file
31
src/Aufgabe3.hs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
-- Aufgabe 3
|
||||||
|
-- =========
|
||||||
|
|
||||||
|
module Aufgabe3 where
|
||||||
|
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
import List
|
||||||
|
|
||||||
|
import ERPSys
|
||||||
|
|
||||||
|
import Aufgabe2
|
||||||
|
|
||||||
|
-- Die Funktion scan soll, aus einer `ProductList` (2. Argument) anhand eines
|
||||||
|
-- Barcodes (1. Argument) einen Artikel finden und diesen dann in eine
|
||||||
|
-- Scannerliste einfügen. Wurde kein Artiekl gefunden gibt `scan` `Nothing` zurück.
|
||||||
|
-- Um die eigentliche Funktion `scan` zu implementieren, empfiehlt es sich, zuerst
|
||||||
|
-- eine Instanz `Eq` für `Article` zu definieren.
|
||||||
|
-- Diese sollte anhand des Barcodes die Gleichheit eines Artikels bestimmen.
|
||||||
|
|
||||||
|
scan :: (Eq a) => a -> ProductList a b c -> ScannerList a b c -> Maybe (ScannerList a b c)
|
||||||
|
|
||||||
|
scan = undefined
|
||||||
|
|
||||||
|
instance (Eq a) => Eq (Article a b c) where
|
||||||
|
|
||||||
|
(==) = undefined
|
||||||
|
|
||||||
|
result = show $ scan 1 productCatalog
|
||||||
|
$ fromMaybe AmountListEnd $ scan 2 productCatalog
|
||||||
|
$ fromMaybe AmountListEnd $ scan 1 productCatalog AmountListEnd
|
31
src/Aufgabe3.lhs
Normal file
31
src/Aufgabe3.lhs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Aufgabe 3
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe3 where
|
||||||
|
>
|
||||||
|
> import Data.Maybe (fromMaybe)
|
||||||
|
>
|
||||||
|
> import List
|
||||||
|
>
|
||||||
|
> import ERPSys
|
||||||
|
>
|
||||||
|
> import Aufgabe2
|
||||||
|
|
||||||
|
Die Funktion scan soll, aus einer `ProductList` (2. Argument) anhand eines
|
||||||
|
Barcodes (1. Argument) einen Artikel finden und diesen dann in eine
|
||||||
|
Scannerliste einfügen. Wurde kein Artiekl gefunden gibt `scan` `Nothing` zurück.
|
||||||
|
Um die eigentliche Funktion `scan` zu implementieren, empfiehlt es sich, zuerst
|
||||||
|
eine Instanz `Eq` für `Article` zu definieren.
|
||||||
|
Diese sollte anhand des Barcodes die Gleichheit eines Artikels bestimmen.
|
||||||
|
|
||||||
|
> scan :: (Eq a) => a -> ProductList a b c -> ScannerList a b c -> Maybe (ScannerList a b c)
|
||||||
|
>
|
||||||
|
> scan = undefined
|
||||||
|
|
||||||
|
> instance (Eq a) => Eq (Article a b c) where
|
||||||
|
>
|
||||||
|
> (==) = undefined
|
||||||
|
|
||||||
|
> result = show $ scan 1 productCatalog
|
||||||
|
> $ fromMaybe AmountListEnd $ scan 2 productCatalog
|
||||||
|
> $ fromMaybe AmountListEnd $ scan 1 productCatalog AmountListEnd
|
31
src/Aufgabe3.md
Normal file
31
src/Aufgabe3.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Aufgabe 3
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe3 where
|
||||||
|
>
|
||||||
|
> import Data.Maybe (fromMaybe)
|
||||||
|
>
|
||||||
|
> import List
|
||||||
|
>
|
||||||
|
> import ERPSys
|
||||||
|
>
|
||||||
|
> import Aufgabe2
|
||||||
|
|
||||||
|
Die Funktion scan soll, aus einer `ProductList` (2. Argument) anhand eines
|
||||||
|
Barcodes (1. Argument) einen Artikel finden und diesen dann in eine
|
||||||
|
Scannerliste einfügen. Wurde kein Artiekl gefunden gibt `scan` `Nothing` zurück.
|
||||||
|
Um die eigentliche Funktion `scan` zu implementieren, empfiehlt es sich, zuerst
|
||||||
|
eine Instanz `Eq` für `Article` zu definieren.
|
||||||
|
Diese sollte anhand des Barcodes die Gleichheit eines Artikels bestimmen.
|
||||||
|
|
||||||
|
> scan :: (Eq a) => a -> ProductList a b c -> ScannerList a b c -> Maybe (ScannerList a b c)
|
||||||
|
>
|
||||||
|
> scan = undefined
|
||||||
|
|
||||||
|
> instance (Eq a) => Eq (Article a b c) where
|
||||||
|
>
|
||||||
|
> (==) = undefined
|
||||||
|
|
||||||
|
> result = show $ scan 1 productCatalog
|
||||||
|
> $ fromMaybe AmountListEnd $ scan 2 productCatalog
|
||||||
|
> $ fromMaybe AmountListEnd $ scan 1 productCatalog AmountListEnd
|
40
src/Aufgabe4.hs
Normal file
40
src/Aufgabe4.hs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
-- Aufgabe 4
|
||||||
|
-- =========
|
||||||
|
|
||||||
|
module Aufgabe4 where
|
||||||
|
|
||||||
|
import Lib
|
||||||
|
import Aufgabe2
|
||||||
|
import Aufgabe3
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
-- Nun da eine `ScannerList` erstellt werden kann, wird eine Funktion, die einen Kassenbon erstellen kann, benötigt.
|
||||||
|
-- Dieser sollte angemessen formatiert sein.
|
||||||
|
-- Die Funktion `generateBill` soll diese Aufgabe übernehmen.
|
||||||
|
|
||||||
|
type Bill = String
|
||||||
|
|
||||||
|
generateBill :: (Show a, Show b, Show c) => ScannerList a b c -> Bill
|
||||||
|
|
||||||
|
generateBill = undefined
|
||||||
|
|
||||||
|
|
||||||
|
result = generateBill scannerList
|
||||||
|
|
||||||
|
-- Ein paar Hilfsfunktionen zum generieren einer `ScannerList` asu einer Liste
|
||||||
|
-- von Barcodes. /Glücklicherweise/ hat diese bereits ein Kollege von Ihnen entwickelt!
|
||||||
|
-- (Mit anderen Worten: Sie brauchen die unten stehenden Funktionen weder
|
||||||
|
-- anpassen, noch verstehen und auch nicht benutzen, nochmal Glück gehabt ;D )
|
||||||
|
|
||||||
|
scannerList :: ScannerList Int String Float
|
||||||
|
scannerList = fromMaybe AmountListEnd $ scanList [1,3,1,2,1,3]
|
||||||
|
|
||||||
|
scanList :: [Int] -> Maybe (ScannerList Int String Float)
|
||||||
|
scanList l = let help :: [Int] -> Maybe (ScannerList Int String Float) -> Maybe (ScannerList Int String Float)
|
||||||
|
help = flip $ foldl (\sl a -> sl >>= preparedScan a)
|
||||||
|
in help l $ Just AmountListEnd
|
||||||
|
|
||||||
|
preparedScan :: Int -> ScannerList Int String Float -> Maybe (ScannerList Int String Float)
|
||||||
|
|
||||||
|
preparedScan = flip scan productCatalog
|
||||||
|
|
40
src/Aufgabe4.lhs
Normal file
40
src/Aufgabe4.lhs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Aufgabe 4
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe4 where
|
||||||
|
>
|
||||||
|
> import Lib
|
||||||
|
> import Aufgabe2
|
||||||
|
> import Aufgabe3
|
||||||
|
> import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
Nun da eine `ScannerList` erstellt werden kann, wird eine Funktion, die einen Kassenbon erstellen kann, benötigt.
|
||||||
|
Dieser sollte /angemessen/ formatiert sein.
|
||||||
|
Die Funktion `generateBill` soll diese Aufgabe übernehmen.
|
||||||
|
|
||||||
|
> type Bill = String
|
||||||
|
>
|
||||||
|
> generateBill :: (Show a, Show b, Show c) => ScannerList a b c -> Bill
|
||||||
|
>
|
||||||
|
> generateBill = undefined
|
||||||
|
|
||||||
|
|
||||||
|
> result = generateBill scannerList
|
||||||
|
|
||||||
|
Ein paar Hilfsfunktionen zum generieren einer `ScannerList` asu einer Liste
|
||||||
|
von Barcodes. /Glücklicherweise/ hat diese bereits ein Kollege von Ihnen entwickelt!
|
||||||
|
(Mit anderen Worten: Sie brauchen die unten stehenden Funktionen weder
|
||||||
|
anpassen, noch verstehen und auch nicht benutzen, nochmal Glück gehabt ;D )
|
||||||
|
|
||||||
|
> scannerList :: ScannerList Int String Float
|
||||||
|
> scannerList = fromMaybe AmountListEnd $ scanList [1,3,1,2,1,3]
|
||||||
|
|
||||||
|
> scanList :: [Int] -> Maybe (ScannerList Int String Float)
|
||||||
|
> scanList l = let help :: [Int] -> Maybe (ScannerList Int String Float) -> Maybe (ScannerList Int String Float)
|
||||||
|
> help = flip $ foldl (\sl a -> sl >>= preparedScan a)
|
||||||
|
> in help l $ Just AmountListEnd
|
||||||
|
|
||||||
|
> preparedScan :: Int -> ScannerList Int String Float -> Maybe (ScannerList Int String Float)
|
||||||
|
>
|
||||||
|
> preparedScan = flip scan productCatalog
|
||||||
|
|
40
src/Aufgabe4.md
Normal file
40
src/Aufgabe4.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Aufgabe 4
|
||||||
|
=========
|
||||||
|
|
||||||
|
> module Aufgabe4 where
|
||||||
|
>
|
||||||
|
> import Lib
|
||||||
|
> import Aufgabe2
|
||||||
|
> import Aufgabe3
|
||||||
|
> import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
Nun da eine `ScannerList` erstellt werden kann, wird eine Funktion, die einen Kassenbon erstellen kann, benötigt.
|
||||||
|
Dieser sollte /angemessen/ formatiert sein.
|
||||||
|
Die Funktion `generateBill` soll diese Aufgabe übernehmen.
|
||||||
|
|
||||||
|
> type Bill = String
|
||||||
|
>
|
||||||
|
> generateBill :: (Show a, Show b, Show c) => ScannerList a b c -> Bill
|
||||||
|
>
|
||||||
|
> generateBill = undefined
|
||||||
|
|
||||||
|
|
||||||
|
> result = generateBill scannerList
|
||||||
|
|
||||||
|
Ein paar Hilfsfunktionen zum generieren einer `ScannerList` asu einer Liste
|
||||||
|
von Barcodes. /Glücklicherweise/ hat diese bereits ein Kollege von Ihnen entwickelt!
|
||||||
|
(Mit anderen Worten: Sie brauchen die unten stehenden Funktionen weder
|
||||||
|
anpassen, noch verstehen und auch nicht benutzen, nochmal Glück gehabt ;D )
|
||||||
|
|
||||||
|
> scannerList :: ScannerList Int String Float
|
||||||
|
> scannerList = fromMaybe AmountListEnd $ scanList [1,3,1,2,1,3]
|
||||||
|
|
||||||
|
> scanList :: [Int] -> Maybe (ScannerList Int String Float)
|
||||||
|
> scanList l = let help :: [Int] -> Maybe (ScannerList Int String Float) -> Maybe (ScannerList Int String Float)
|
||||||
|
> help = flip $ foldl (\sl a -> sl >>= preparedScan a)
|
||||||
|
> in help l $ Just AmountListEnd
|
||||||
|
|
||||||
|
> preparedScan :: Int -> ScannerList Int String Float -> Maybe (ScannerList Int String Float)
|
||||||
|
>
|
||||||
|
> preparedScan = flip scan productCatalog
|
||||||
|
|
18
src/ERPSys.hs
Normal file
18
src/ERPSys.hs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module ERPSys
|
||||||
|
( ProductList
|
||||||
|
, ScannerList
|
||||||
|
, Article(Article)
|
||||||
|
) where
|
||||||
|
|
||||||
|
import List
|
||||||
|
|
||||||
|
type ProductList a b c = List (Article a b c) -- ^ List with Articles
|
||||||
|
type ScannerList a b c = AmountList Int (Article a b c) -- ^ AmountList with Articles
|
||||||
|
|
||||||
|
-- | generic Article isomorph to (,,)
|
||||||
|
data Article a b c = Article
|
||||||
|
{ _barcode :: a
|
||||||
|
, _name :: b
|
||||||
|
, _price :: c
|
||||||
|
} deriving (Show)
|
||||||
|
|
14
src/Lib.hs
Normal file
14
src/Lib.hs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module Lib
|
||||||
|
( ProductList
|
||||||
|
, ScannerList
|
||||||
|
, Article(Article)
|
||||||
|
, List(ListEnd, Element)
|
||||||
|
, AmountList(AmountAndElement, AmountListEnd)
|
||||||
|
, Filter
|
||||||
|
, Searchable(..)
|
||||||
|
, Consumable(..)
|
||||||
|
, Insertable(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
import List
|
||||||
|
import ERPSys
|
123
src/List.hs
Normal file
123
src/List.hs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
module List
|
||||||
|
( List(ListEnd, Element)
|
||||||
|
, AmountList(AmountAndElement, AmountListEnd)
|
||||||
|
, Filter
|
||||||
|
, Searchable(..)
|
||||||
|
, Consumable(..)
|
||||||
|
, Insertable(..)
|
||||||
|
-- , amountOf
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Lens
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
-- | isomorph to []
|
||||||
|
data List a = ListEnd | Element
|
||||||
|
{ _el :: a
|
||||||
|
, _remaining :: (List a)
|
||||||
|
} deriving (Show)
|
||||||
|
|
||||||
|
makeLenses (''List)
|
||||||
|
|
||||||
|
-- | counting list
|
||||||
|
data AmountList a b = AmountListEnd | AmountAndElement
|
||||||
|
{ _amount :: a
|
||||||
|
, _el' :: b
|
||||||
|
, _remaining' :: (AmountList a b)
|
||||||
|
} deriving (Show)
|
||||||
|
|
||||||
|
makeLenses (''AmountList)
|
||||||
|
|
||||||
|
type Filter a = a -> Bool
|
||||||
|
|
||||||
|
instance Monoid (List a) where
|
||||||
|
mempty = ListEnd
|
||||||
|
mappend ListEnd = id
|
||||||
|
mappend a = mappend $ a ^. remaining
|
||||||
|
|
||||||
|
instance Monoid (AmountList a b) where
|
||||||
|
mempty = AmountListEnd
|
||||||
|
mappend AmountListEnd = id
|
||||||
|
mappend a = mappend $ a ^. remaining'
|
||||||
|
|
||||||
|
instance Eq a => Eq (List a) where
|
||||||
|
ListEnd == ListEnd = True
|
||||||
|
a == b = a^?el == b^?el
|
||||||
|
&& a^?remaining == b^?remaining
|
||||||
|
|
||||||
|
instance (Eq a, Eq b) => Eq (AmountList a b) where
|
||||||
|
AmountListEnd == AmountListEnd = True
|
||||||
|
a == b = a^?amount == b^?amount
|
||||||
|
&& a^?el' == b^?el'
|
||||||
|
&& a^?remaining' == b^?remaining'
|
||||||
|
|
||||||
|
-- | find with return type determined by the structure b a
|
||||||
|
class Searchable a b c | b a -> c where
|
||||||
|
findFirst :: Filter a -> b a -> Maybe c
|
||||||
|
|
||||||
|
-- | find first a in list matching the filter
|
||||||
|
instance Searchable a List a where
|
||||||
|
findFirst :: Filter a -> List a -> Maybe a
|
||||||
|
findFirst filter list = list^?el>>=(\el_-> if filter el_
|
||||||
|
then Just el_
|
||||||
|
else findFirst filter $ list^.remaining)
|
||||||
|
|
||||||
|
-- | find first a in list matching the filter returning (amount, element)
|
||||||
|
instance Searchable a (AmountList b) (b, a) where
|
||||||
|
findFirst :: Filter a -> AmountList b a -> Maybe (b, a)
|
||||||
|
findFirst filter list = list^?el' >>= \el_ -> if filter el_
|
||||||
|
then Just (list^?!amount, el_)
|
||||||
|
else list^?remaining' >>= findFirst filter
|
||||||
|
|
||||||
|
class Consumable b a c | b a -> c where
|
||||||
|
consume :: (c -> d -> d) -> d -> b a -> d
|
||||||
|
-- ^ special form of a fold determined by structure b a
|
||||||
|
|
||||||
|
-- | isomorph to a foldr
|
||||||
|
instance Consumable List a a where
|
||||||
|
consume :: (a -> d -> d) -> d -> List a -> d
|
||||||
|
consume _ a ListEnd = a
|
||||||
|
consume f s (Element a as) = f a $ consume f s as
|
||||||
|
|
||||||
|
-- | foldr over (element, amount)
|
||||||
|
instance Consumable (AmountList b) a (a, b) where
|
||||||
|
consume :: ((a, b) -> e -> e) -> e -> AmountList b a -> e
|
||||||
|
consume _ a AmountListEnd = a
|
||||||
|
consume f s (AmountAndElement b a as) = f (a,b) $ consume f s as
|
||||||
|
|
||||||
|
|
||||||
|
{--instance {-# OVERLAPPABLE #-} Consumable (AmountList b) a a where
|
||||||
|
consume :: (a -> e -> e) -> e -> AmountList b a -> e
|
||||||
|
consume _ a AmountListEnd = a
|
||||||
|
consume f s (AmountAndElement b a as) = f a $ consume f s as --}
|
||||||
|
|
||||||
|
class Insertable a b where
|
||||||
|
insert :: a -> b a -> b a
|
||||||
|
-- ^ insert a to structure b
|
||||||
|
|
||||||
|
-- | RTFC!
|
||||||
|
instance Insertable a List where
|
||||||
|
insert :: a -> List a -> List a
|
||||||
|
insert = Element
|
||||||
|
|
||||||
|
-- | insert with amount count += 1
|
||||||
|
instance (Eq a, Num b) => Insertable a (AmountList b) where
|
||||||
|
insert :: a -> AmountList b a -> AmountList b a
|
||||||
|
insert a AmountListEnd = AmountAndElement 1 a AmountListEnd
|
||||||
|
insert a b = case b^?el' & _Just %~ (==a) of
|
||||||
|
Just True -> b & amount +~ 1
|
||||||
|
_ -> b & remaining' %~ (insert a)
|
||||||
|
|
||||||
|
-- | get amount of a in list. returning mempty if not found
|
||||||
|
amountOf :: (Eq a, Monoid b) => a -> AmountList b a -> b
|
||||||
|
amountOf a b = fromMaybe mempty $ b ^. to (findFirst (==a)) & _Just %~ fst
|
||||||
|
--b ^. to findFirst (==a) %~ _1 ^. to fromMaybe mempty
|
||||||
|
-- (Just (c,_)) -> c
|
||||||
|
-- Nothing -> mempty
|
||||||
|
|
66
stack.yaml
Normal file
66
stack.yaml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# This file was automatically generated by 'stack init'
|
||||||
|
#
|
||||||
|
# Some commonly used options have been documented as comments in this file.
|
||||||
|
# For advanced use and comprehensive documentation of the format, please see:
|
||||||
|
# http://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||||
|
|
||||||
|
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||||
|
# A snapshot resolver dictates the compiler version and the set of packages
|
||||||
|
# to be used for project dependencies. For example:
|
||||||
|
#
|
||||||
|
# resolver: lts-3.5
|
||||||
|
# resolver: nightly-2015-09-21
|
||||||
|
# resolver: ghc-7.10.2
|
||||||
|
# resolver: ghcjs-0.1.0_ghc-7.10.2
|
||||||
|
# resolver:
|
||||||
|
# name: custom-snapshot
|
||||||
|
# location: "./custom-snapshot.yaml"
|
||||||
|
resolver: lts-8.12
|
||||||
|
|
||||||
|
# User packages to be built.
|
||||||
|
# Various formats can be used as shown in the example below.
|
||||||
|
#
|
||||||
|
# packages:
|
||||||
|
# - some-directory
|
||||||
|
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||||
|
# - location:
|
||||||
|
# git: https://github.com/commercialhaskell/stack.git
|
||||||
|
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||||
|
# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||||
|
# extra-dep: true
|
||||||
|
# subdirs:
|
||||||
|
# - auto-update
|
||||||
|
# - wai
|
||||||
|
#
|
||||||
|
# A package marked 'extra-dep: true' will only be built if demanded by a
|
||||||
|
# non-dependency (i.e. a user package), and its test suites and benchmarks
|
||||||
|
# will not be run. This is useful for tweaking upstream packages.
|
||||||
|
packages:
|
||||||
|
- '.'
|
||||||
|
# Dependency packages to be pulled from upstream that are not in the resolver
|
||||||
|
# (e.g., acme-missiles-0.3)
|
||||||
|
extra-deps: []
|
||||||
|
|
||||||
|
# Override default flag values for local packages and extra-deps
|
||||||
|
flags: {}
|
||||||
|
|
||||||
|
# Extra package databases containing global packages
|
||||||
|
extra-package-dbs: []
|
||||||
|
|
||||||
|
# Control whether we use the GHC we find on the path
|
||||||
|
# system-ghc: true
|
||||||
|
#
|
||||||
|
# Require a specific version of stack, using version ranges
|
||||||
|
# require-stack-version: -any # Default
|
||||||
|
# require-stack-version: ">=1.1"
|
||||||
|
#
|
||||||
|
# Override the architecture used by stack, especially useful on Windows
|
||||||
|
# arch: i386
|
||||||
|
# arch: x86_64
|
||||||
|
#
|
||||||
|
# Extra directories used by stack for building
|
||||||
|
# extra-include-dirs: [/path/to/dir]
|
||||||
|
# extra-lib-dirs: [/path/to/dir]
|
||||||
|
#
|
||||||
|
# Allow a newer minor version of GHC than the snapshot specifies
|
||||||
|
# compiler-check: newer-minor
|
17
test/Aufgabe1-Spec.hs
Normal file
17
test/Aufgabe1-Spec.hs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Aufgabe1
|
||||||
|
|
||||||
|
import Test.Framework.Providers.HUnit (testCase)
|
||||||
|
import Test.Framework.Runners.Console (defaultMain)
|
||||||
|
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
test1 = testCase "filter funktioniert" $ assertEqual "Vowel filter" "Hll Wrld!" result
|
||||||
|
|
||||||
|
testSentence2 = "Is really EVERY VowEL of this uSEleSS SentencE remOved?"
|
||||||
|
testResult2 = "s rlly VRY VwL f ths SlSS Sntnc rmvd?"
|
||||||
|
test2 = testCase "filter test" $ assertEqual testSentence2 testResult2 $ filterVowels testSentence2
|
||||||
|
|
||||||
|
tests = [test1, test2]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = defaultMain tests
|
40
test/Aufgabe2-Spec.hs
Normal file
40
test/Aufgabe2-Spec.hs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import Aufgabe2
|
||||||
|
|
||||||
|
import Test.Framework.Providers.HUnit (testCase)
|
||||||
|
import Test.Framework.Runners.Console (defaultMain)
|
||||||
|
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
import Lib
|
||||||
|
|
||||||
|
instance (Eq a, Eq b, Eq c) => Eq (Article a b c) where
|
||||||
|
(Article a b c) == (Article a' b' c') = a == a' && b == b' && c == c'
|
||||||
|
|
||||||
|
data TestProd = Tp1 | Tp2 | Tp3 deriving (Eq, Show)
|
||||||
|
|
||||||
|
emptyProductList :: ProductList Int () ()
|
||||||
|
emptyProductList = ListEnd
|
||||||
|
|
||||||
|
productList :: ProductList Int TestProd ()
|
||||||
|
productList = insert (Article 0 Tp1 ())
|
||||||
|
$ insert (Article 1 Tp2 ())
|
||||||
|
$ insert (Article 2 Tp3 ())
|
||||||
|
$ ListEnd
|
||||||
|
|
||||||
|
emptyFind = testCase "Suche in leerer Liste"
|
||||||
|
$ assertEqual "empty list search" Nothing
|
||||||
|
$ findArticle 0 emptyProductList
|
||||||
|
|
||||||
|
findNone = testCase "Suche nach nicht vorhandenem"
|
||||||
|
$ assertEqual "find nothing" Nothing
|
||||||
|
$ findArticle 3 productList
|
||||||
|
|
||||||
|
findSome = testCase "Suche nach vorhandenem"
|
||||||
|
$ assertEqual "find some" (Just $ Article 0 Tp1 ())
|
||||||
|
$ findArticle 0 productList
|
||||||
|
|
||||||
|
|
||||||
|
tests = [emptyFind, findNone, findSome]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = defaultMain tests
|
63
test/Aufgabe3-Spec.hs
Normal file
63
test/Aufgabe3-Spec.hs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import Aufgabe3
|
||||||
|
|
||||||
|
import Test.Framework.Providers.HUnit (testCase)
|
||||||
|
import Test.Framework.Runners.Console (defaultMain)
|
||||||
|
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
import Lib
|
||||||
|
|
||||||
|
data TestProd = Tp1 | Tp2 | Tp3 deriving (Eq, Show)
|
||||||
|
|
||||||
|
productList :: ProductList Int TestProd ()
|
||||||
|
productList = insert (Article 0 Tp1 ())
|
||||||
|
$ insert (Article 1 Tp2 ())
|
||||||
|
$ insert (Article 2 Tp3 ())
|
||||||
|
$ ListEnd
|
||||||
|
|
||||||
|
emptyScannerList :: ScannerList Int TestProd ()
|
||||||
|
emptyScannerList = AmountListEnd
|
||||||
|
|
||||||
|
scannerList1 = scan 0 productList emptyScannerList
|
||||||
|
scannerList2 = scan 9 productList emptyScannerList
|
||||||
|
scannerList3 = scannerList1 >>= scan 0 productList
|
||||||
|
scannerList4 = scannerList3 >>= scan 1 productList
|
||||||
|
scannerList5 = scannerList4 >>= scan 2 productList
|
||||||
|
scannerList6 = scannerList5 >>= scan 9 productList
|
||||||
|
scannerList7 = scannerList5 >>= scan 1 productList
|
||||||
|
scannerList8 = scannerList7 >>= scan 0 productList
|
||||||
|
scannerList9 = scannerList8 >>= scan 9 productList
|
||||||
|
|
||||||
|
|
||||||
|
scan1 = testCase "Scan, existing product, list size: 0 "
|
||||||
|
$ assertEqual "scan 1" (Just $ AmountAndElement 1 (Article 0 Tp1 ()) AmountListEnd) scannerList1
|
||||||
|
|
||||||
|
scan2 = testCase "Scan, not existing product, list size: 0 "
|
||||||
|
$ assertEqual "scan 2" Nothing scannerList2
|
||||||
|
|
||||||
|
scan3 = testCase "Scan, existing product, list size: 1, product already in list"
|
||||||
|
$ assertEqual "scan 3" (Just $ AmountAndElement 2 (Article 0 Tp1 ()) AmountListEnd) scannerList3
|
||||||
|
|
||||||
|
scan4 = testCase "Scan, existing product, list size: 1, product not in list "
|
||||||
|
$ assertEqual "scan 4" (Just $ AmountAndElement 2 (Article 0 Tp1 ()) $ AmountAndElement 1 (Article 1 Tp2 ()) AmountListEnd) scannerList4
|
||||||
|
|
||||||
|
scan5 = testCase "Scan, existing product, list size: 2, product not in list "
|
||||||
|
$ assertEqual "scan 5" (Just $ AmountAndElement 2 (Article 0 Tp1 ()) $ AmountAndElement 1 (Article 1 Tp2 ()) $ AmountAndElement 1 (Article 2 Tp3 ()) AmountListEnd) scannerList5
|
||||||
|
|
||||||
|
scan6 = testCase "Scan, not existing product, list size: 2 "
|
||||||
|
$ assertEqual "scan 3" Nothing scannerList6
|
||||||
|
|
||||||
|
scan7 = testCase "Scan, existing product, list size: 3, product in list "
|
||||||
|
$ assertEqual "scan 7" (Just $ AmountAndElement 2 (Article 0 Tp1 ()) $ AmountAndElement 2 (Article 1 Tp2 ()) $ AmountAndElement 1 (Article 2 Tp3 ()) AmountListEnd) scannerList7
|
||||||
|
|
||||||
|
scan8 = testCase "Scan, existing product, list size: 3, product in list "
|
||||||
|
$ assertEqual "scan 8" (Just $ AmountAndElement 3 (Article 0 Tp1 ()) $ AmountAndElement 2 (Article 1 Tp2 ()) $ AmountAndElement 1 (Article 2 Tp3 ()) AmountListEnd) scannerList8
|
||||||
|
|
||||||
|
scan9 = testCase "Scan, not existing product, list size: 3 "
|
||||||
|
$ assertEqual "scan 9" Nothing scannerList9
|
||||||
|
|
||||||
|
|
||||||
|
tests = [scan1, scan2, scan3, scan4, scan5, scan6, scan7, scan8, scan9]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = defaultMain tests
|
4
test/Aufgabe4-Spec.hs
Normal file
4
test/Aufgabe4-Spec.hs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
putStrLn "Da Ihnen in dieser Aufgabe Platz für Kreativität eingeräumt wurde,"
|
||||||
|
putStrLn "lässt sich Ihre Lösung leider nicht automatisiert überprüfen."
|
111
zettel1.cabal
Normal file
111
zettel1.cabal
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
name: zettel1
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: First Assignment of FFPiHaskell 2017
|
||||||
|
-- description:
|
||||||
|
homepage: https://github.com/FFPiHaskell/zettel1-skeleton#readme
|
||||||
|
license: BSD3
|
||||||
|
license-file: LICENSE
|
||||||
|
author: FFPiHaskell Tutors
|
||||||
|
maintainer: sdressel@techfak.uni-bielefeld.de
|
||||||
|
copyright: 2017 FFPiHaskell Tutors
|
||||||
|
category: cli
|
||||||
|
build-type: Simple
|
||||||
|
extra-source-files: README.md
|
||||||
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
|
||||||
|
-- library for all things common in all exercises/not neccessary for students
|
||||||
|
-- to solve assignments
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
exposed-modules: Lib
|
||||||
|
, Aufgabe1
|
||||||
|
, Aufgabe2
|
||||||
|
, Aufgabe3
|
||||||
|
, Aufgabe4
|
||||||
|
, List
|
||||||
|
, ERPSys
|
||||||
|
build-depends: base >= 4.7 && < 5
|
||||||
|
, lens
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable aufgabe1
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Aufgabe1Main.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite aufgabe1-tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: test
|
||||||
|
main-is: Aufgabe1-Spec.hs
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
, test-framework
|
||||||
|
, test-framework-hunit
|
||||||
|
, HUnit
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable aufgabe2
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Aufgabe2Main.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite aufgabe2-tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: test
|
||||||
|
main-is: Aufgabe2-Spec.hs
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
, test-framework
|
||||||
|
, test-framework-hunit
|
||||||
|
, HUnit
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable aufgabe3
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Aufgabe3Main.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite aufgabe3-tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: test
|
||||||
|
main-is: Aufgabe3-Spec.hs
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
, test-framework
|
||||||
|
, test-framework-hunit
|
||||||
|
, HUnit
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable aufgabe4
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Aufgabe4Main.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite aufgabe4-tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: test
|
||||||
|
main-is: Aufgabe4-Spec.hs
|
||||||
|
build-depends: base
|
||||||
|
, zettel1
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/FFPiHaskell/zettel1-skeleton
|
Loading…
Reference in New Issue
Block a user