Wie schon $immer hat man nie genug Zeit sich seinen Hobbies zu frönen. Ein Hobby wäre z.B. in der programmiersprache Haskell zu programmieren. Nun bin ich über "Learn You a Haskell" gestossen, was eine recht abgedrehte Haskelleinleitung ist (kann man auch kostenlos online lesen). Ich denke damit sollte es jedem Spaß machen Haskell zu lernen. Zwecks Wiederholung überfliege ich das Buch derzeit und finde dass es hier mal erwähnt werden sollte, nachdem ich per aktuellem Linux-Magazin unter den Buchvorstellungen darauf aufmerksam geworden bin.
Recently in Declarative programming Category
Um meine Haskellkenntnisse wieder aufzufrischen (in den letzten 3 Monaten habe ich dort relativ wenig gemacht aufgrund anderer Dinge) habe ich mir das Buch Programming in Haskell von Graham Hutton gegönnt.
Es dient Prima als Nachschlagewerk. Wer allerdings keine Lust auf trockenes Lesen hat, der kann sich den darauf basierenden Video-Lectures zuwenden.
type 'a lazy = unit -> 'a;
fun force (f:'a lazy) = f ();
fun delay x = (fn () => x) : 'a lazy;
datatype 'a sequ = NIL | CONS of 'a * 'a sequ lazy;
fun first 0 s = []
| first n NIL = []
| first n (CONS (i,r)) = i :: first (n-1) (force r);
fun filters p NIL = NIL
| filters p (CONS (x,r)) =
if p x
then CONS (x, fn () => filters p (force r))
else filters p (force r);
fun nat_paare () =
let
fun from_pair (x,0) =
CONS ((x,0), fn () => from_pair (0,x+1))
| from_pair (up,dn) =
CONS ((up,dn), fn () => from_pair (up+1,dn-1))
in from_pair (0,0)
end;
(* Test
val test = first 10 (nat_paare ())
*)
fun nat_paare_nicht_null () =
filters (fn (x,y) => x > 0 andalso y > 0) (nat_paare ());
(* Test
val test = first 10 (nat_paare_nicht_null ());
*)
Da Haskell bereits Lazy Evaluation eingebaut hat, geht es hier einfacher. Hier muss auch kein neuer Datentyp definiert werden, da Haskell-Listen bereits lazy sind.:
{- Just to make it look like the ML example -}
first = take
filters = filter
{- Implementation -}
nat_paare = from_pair 0 0
where
from_pair x 0 = [x,0] : from_pair 0 (x+1)
from_pair up dn = [up,dn] : from_pair (up+1) (dn-1)
{- Test:
first 10 nat_paare
-}
nat_paare_nicht_null =
filters (\[x,y] -> x > 0 && y > 0) nat_paare
{- Test:
first 10 nat_paare_nicht_null
-}
fun make_map_fn f1 = fn (x,y) => f1 x :: y
make_map_fn f1 = \x y -> f1 x : y
fun make_filter_fn f1 =
fn (x,y) => if f1 x then x :: y else y
make_filter_fn f1 =
\x y -> if f1 then x : y else y
fun my_map f l = foldr (make_map_fn f) [] l
my_map f l = foldr (make_map_fn f) [] l
fun my_filter f l = foldr (make_filter_fn f) [] l
my_filter f l = foldr (make_filter_fn f) [] l
Die Haskell Syntax ist darauf optimiert so wenig Boilerplate Code wie möglich zu produzieren. Standard ML ist da allerdings auch nicht gerade schlecht (die Funktionen my_map und my_filter haben in Haskell und in SML quasi die selbe Syntax. SML benutzt lediglich noch das Schlüsselwort fun).
Die interaktive SML shell lässt zu Wünschen übrig. So versuch ich vergebens einen Befehl die aktuell geladene Datei erneut einzulesen. In Haskell (ghci) geht das z.B. mit dem Befehl :r (r für reload) wie folgt:
*Main> :r [1 of 1] Compiling Main ( temp.hs, interpreted ) Ok, modules loaded: Main.
Bei SML hingegen muss ich mit Strg+D den interaktiven Prompt verlassen und die Bash-Histoy benutzen um "sml meinesourcecodedatei.sml" erneut einzulesen. Zwar gibt es einen sml-Befehl eine Sourcecodedatei einzulesen, aber der ist zu lang um ihn jedes Mal erneut eingeben zu können (Mein sml hat auch keine History-Funktion).
Standard ML:
datatype ''a multi
= EMPTY
| ELEM of ''a
| UNION of ''a multi * ''a multi
Haskell:
data (Eq a) => Multi a
= Empty
| Elem a
| Union (Multi a) (Multi a)
deriving Show
Standard ML:
fun number (EMPTY) _ = 0
| number (ELEM x) w = if x = w then 1 else 0
| number (UNION (x,y)) w = (number x w) + (number y w)
fun test_number w =
number (UNION (
EMPTY,
UNION (
ELEM 4,
UNION (
ELEM 6,
UNION (
UNION (
ELEM 4,
ELEM 4
),
EMPTY)
)
)
)) w
Haskell:
number Empty _ = 0
number (Elem x) w = if x == w then 1 else 0
test_number w =
number (Union
Empty
(Union
(Elem 4)
(Union
(Elem 6)
(Union
(Union
(Elem 4)
(Elem 4)
)
Empty)
)
)
) w
Standard ML:
fun simplify (UNION (x,y)) =
let fun is_empty (EMPTY) = true
| is_empty _ = false
val x' = simplify x
val y' = simplify y
in if (is_empty x') andalso (is_empty y')
then EMPTY
else if (is_empty x')
then y'
else if (is_empty y')
then x'
else UNION (x', y')
end
| simplify x = x
Haskell:
simplify (Union x y)
| (isEmpty x') && (isEmpty y') = Empty
| isEmpty x' = y'
| isEmpty y' = x'
| otherwise = Union x' y'
where
isEmpty Empty = True
isEmpty _ = False
x' = simplify x
y' = simplify y
simplify x = x
Standard ML:
fun delete_all m w =
let fun delete_all' (ELEM x) = if x = w then EMPTY else ELEM x
| delete_all' (UNION (x,y)) = UNION (delete_all' x, delete_all' y)
| delete_all' x = x
in simplify (delete_all' m)
end
Haskell:
delete_all m w = simplify (delete_all' m)
where
delete_all' (Elem x) = if x == w then Empty else Elem x
delete_all' (Union x y) = Union (delete_all' x) (delete_all' y)
delete_all' x = x
Standard ML:
fun delete_one m w =
let fun delete_one' (UNION (x,y)) =
let val (x', deleted) = delete_one' x
in if deleted
then (UNION (x', y), deleted)
else let val (y', deleted) = delete_one' y
in (UNION (x, y'), deleted)
end
end
| delete_one' (ELEM x) =
if x = w then (EMPTY, true) else (ELEM x, false)
| delete_one' x = (x, false)
val (m', _) = delete_one' m
in simplify m'
end
Haskell:
delete_one m w = do
let (m', _) = delete_one' m
simplify m'
where
delete_one' (Union x y) =
let (x', deleted) = delete_one' x
in if deleted
then (Union x' y, deleted)
else let (y', deleted) = delete_one' y
in (Union x y', deleted)
delete_one' (Elem x) =
if x == w then (Empty, True) else (Elem x, False)
delete_one' x = (x, False)
Ich hab nun eine Gruppe auf Xing gegründet. Und zwar "Deklarative Programmierung".
Die deklarative Programmierung ist ein Programmierparadigma, bei dem die Beschreibung des Problems im Vordergrund steht. Der Lösungsweg wird dann "automatisch" ermittelt. Zu den deklarativen Programmiersprachen gehören:
funktionale Sprachen (z. B. LISP, ML, Miranda, Gofer, Haskell, Erlang)
logische Sprachen (z. B. Prolog) und einige mehr. Deklarative Programmierung unterscheidet sich somit von dem verbreiteteren Programmierparadigma der imperativen Programmierung.
Freue mich immer auf neue Mitglieder! (Auch personen die sich noch nicht mit der deklarativen Programmierung auskennen sind herzlich eingeladen).
sub ev
{
my $term = $_[0];
if($term =~ /^$con/)
{
return Return($1);
}
elsif($term=~/^$div/)
{
my $numer=$1; my $denom=$3;
return DO {
my $n <- ev($numer);
my $d <- ev($denom);
my $g <- tick();
Return( $n / $d );
}
}else{die "Syntax Error: $term";}
}
Mittlerweile hab ich das Buch Funktionale Programmierung.: Sprachdesign und Programmiertechnik durch. Hier erstmal ein Quote von wlt158 @ Amazon:
Das Buch ist ordentlich geschrieben, aber die Thematik ist für Einsame, denn, auch wenn es wirklich spannend und zukunftssicher ist, man geht einen akademischen Weg, einen Einsiedlerweg, oder für Optimisten: einen Königsweg, denn die deklarative Programmiung, wozu die funktionale Programmiung ja gehört, ist einfach die Zukunft - da gibts kein Wenn und Aber. Doch man wird sich über dieses spannende Thema in keinem Zug und keinem Bus mit keinem einzigen Nichtspezialisiten unterhalten können, denn das, was da drin steht, blicken 99% der Menschen um einen rum definitv nicht. Geschweige denn der oder die Lebenspartner/in. Ausnahme: Man arbeitet in einer Spezialabteilung für funktionale Programmierung. Ihr mutigen Pioniere! Mein Kompliment für das Buch.
Ich bin NICHT der Meinung, dass deklarative Programmierung die Zukunft ALLEINE sein wird. Imperative Sprachen werden in der Zukunft auch weiterhin die Oberhand behalten. Allerdings werden imperative Sprachen von deklarativen Sprachen immer mehr beeinflusst werden. Fast alle modernen imperativen Programmierprachen haben bereits jetzt einen gesunden Anteil funktionaler (deklarativer) Sprachelemente enthalten. Z.B. gibt es in C++0x sowie C# bereits Lambda-Funktionen.
Die Zukunft wird vermutlich in den General Purpose Misch-Sprachen und in den Domain-Specific Sprachen liegen. Rein-Funktionale Sprachen, wie Haskell, werden immer ein Nischendasein leben. Allerdings wirds immer eine Daseinsberechtigung geben, da alleine der Community-Kreis groß genug sein wird.
Letztendlich kann ich Jedem, der sich für funktionale Programmierung etwas tiefer auseinadersetzen möchte, dieses Buch empfehlen.
Als nächstes steht bei mir nun "Programming in Prolog" an :)
I've mentioned this book once before.
Structure and Interpretation of Computer Programs has been MIT's introductory pre-professional computer science subject since 1981. It emphasizes the role of computer languages as vehicles for expressing knowledge and it presents basic principles of abstraction and modularity, together with essential techniques for designing and implementing computer languages. This course has had a worldwide impact on computer science curricula over the past two decades.
You can find the online videos and the free online book right here. For the case the ftp servers are busy you can download them from my own pub ftp instead (ftp.buetow.org/pub).
I've just ordered a new book (in german language) called "Funktionale Programmierung: Sprachdesign und Programmiertechnik " (in english "Functional programming: Language design and programming techniques"). This book is for people who know already a little bit about functional programming but want to dig deeper a little bit! It is demonstrating lots of stuff using functional programming languages such as Haskell and Opal.
