Page
1
Magical Haskell A Friendly Approach to Modern Functional Programming, Type Theory, and Artificial Intelligence ― Anton Antich
Page
2
Magical Haskell A Friendly Approach to Modern Functional Programming, Type Theory, and Artificial Intelligence Anton Antich
Page
3
Magical Haskell: A Friendly Approach to Modern Functional Programming, Type Theory, and Artificial Intelligence ISBN-13 (pbk): 979-8-8688-1281-1 ISBN-13 (electronic): 979-8-8688-1282-8 https://doi.org/10.1007/979-8-8688-1282-8 Copyright © 2025 by Anton Antich This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights. While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made. The publisher makes no warranty, express or implied, with respect to the material contained herein. Managing Director, Apress Media LLC: Welmoed Spahr Acquisitions Editor: Melissa Duffy Development Editor: James Markham Coordinating Editor: Gryffin Winkler Cover designed by eStudioCalamar Distributed to the book trade worldwide by Springer Science+Business Media New York, 1 New York Plaza, New York, NY 10004. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com. Apress Media, LLC is a Delaware LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation. For information on translations, please e-mail booktranslations@springernature.com; for reprint, paperback, or audio rights, please e-mail bookpermissions@springernature.com. Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales web page at http://www.apress.com/bulk-sales. Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub (https://github.com/Apress). For more detailed information, please visit https://www.apress.com/gp/services/source-code. If disposing of this product, please recycle the paper Anton Antich Schaffhausen, Schaffhausen, Switzerland
Page
4
To my parents for making me curious and my wife for her patience, support, and inspiration while working on this book.
Page
5
(This page has no text content)
Page
6
(This page has no text content)
Page
7
(This page has no text content)
Page
8
(This page has no text content)
Page
9
(This page has no text content)
Page
10
xi About the Author Anton Antich is a serial entrepreneur and AI/Type Theory researcher, who majored initially in physics. In various executive roles, he was instrumental in building Veeam Software from 0 to over 1B USD in annual sales in under ten years – making Veeam the fastest-growing European company ever. Upon exiting Veeam, he invested in and helped scale over 20 startups and in the recent years got back to the roots and is currently building Integrail (https:// integrail.ai) – a no-code Agentic AI platform. Haskell has been an integral part of many of the projects undertaken during Anton’s tenure, and his current startup will use it as an optional backend for AI multi-agent execution.
Page
11
xiii About the Technical Reviewer German Gonzalez-Morris is a polyglot software architect/engineer with 20+ years in the field, with knowledge in Java, Spring Boot, C/C++, Julia, Python, Haskell, and JavaScript, among others. He works with cloud (architecture), web-distributed applications, and micro-services. German loves math puzzles (including reading Knuth, proud by solving some of Don's puzzles), swimming, and table tennis. Also, he has reviewed several books, including an application container book (Weblogic) and books on languages (C, Java, Spring, Python, Haskell, TypeScript, WebAssembly, Math for coders, regexp, Julia, Data Structures and Algorithms, Kafka).
Page
12
xv Acknowledgments There are too many people I would like to acknowledge for making this book a reality, and I would like to list at least a few. My aunt Yulia for making me fall in love with physics at the age of six – and without physics there would be no journey to Haskell for me – I do hope you are in the better world now. Richard Feynman for inspiring me to be a better scientist even without formally being one. All the amazing people working on making Haskell, and GHC specifically, the cutting edge of computer science. Ratmir Timashev for everything I’ve learned doing business and for making Agentic AI at Integrail a reality. My grandfather for giving me an amazing C book when all I knew was Pascal. My parents for making me curious and giving me the “programmable calculator MK-61” 40 years ago, the programming platform before all others. My lovely wife, Anastasia, for supporting me in everything I do and for the patience with me while working on this book. The Creator of the Universe for making all of it possible.
Page
13
xvii Introduction Since I was six years old, I wanted to be a nuclear physicist. The idea of being captivated by the beauty of how the world works, expressed in the language of mathematics, fascinated me. Later in life it transformed to being captivated by the beauty of mathematics itself regardless of applications – physics, AI, modeling of advanced business processes in sales, or election results. I studied physics as planned; did research for some time; and learned a bunch of programming languages starting with Pascal and Fortran via old books in my father’s library and moving to C, then to C++, and finally to Java, as it became arguably the most fashionable language in the 1990s, and used all of them professionally in various capacities. Then, I switched to the business side of things and stopped programming, but always kept math and research as a “hobby” of sorts. Then, I discovered Haskell. Oh, how I wish that I’d discovered it sooner. No other practical language suitable for the creation of high-performance production apps comes closer to pure math than Haskell. No other language gives you goosebumps from the code you write. Discovering it led to a bumpy journey toward Type Theory and modest Category Theory beginnings, where the beauty of math combined with the ability to write code resulted in something beautiful and practical. This journey took about ten years, with lots of frustrations along the way. The experience of this journey allowed me to formulate hopefully a somewhat different approach to teaching Haskell than what has been available so far – and delivering it is the purpose of this book.
Page
14
xviii As I was working on it, an AI revolution happened and I started an Agentic AI company along the way – thus, the second half of this book is fully dedicated to Agentic AI and approaches to implementing it in Haskell. This book is for anyone who is interested in learning Haskell, maybe made a couple of attempts and got frustrated by not understanding how to combine all the types into the working program or what monads are. I hope some of the pitfalls I fell into while learning you will be able to avoid using the carefully-built-from-the-ground-up knowledge tree of types, functions, typeclasses, and other abstractions, introduced gently and with practical examples. And even if you do not use Haskell in production anytime soon, learning these principles will make you a better programmer in any other language. I hope you will enjoy it as much as I loved working on it. InTroduCTIon
Page
15
xix How This Book Came to Be: Instead of an Introduction Feel free to skip this somewhat philosophical intro right to Chapter 1. Lately, I've been spending quite a bit of time with Type Theory, lambda cube (e.g., implementing System F-omega-ish type library in CoffeeScript for the fun of finding out how things work as Dr. Feynman used to say), toy functional languages (Haskell is great, but what would a great functional language look like if it were designed today – with all that we've learned from state-of-the-art Haskell development in the last 20 years?), parsers, GUI libraries design, and functional reactive programming. Three thoughts persisted: "I need to write another monad tutorial" – haha, got ya. “How do I teach functional programming to my kids?” – so that it’s light, comprehensible, fun and conveys the beauty of the concepts involved. And “we’ve been doing it all wrong.” Okay, the latter may be an exaggeration, but I need to drive the point across. Like many unfortunate souls before me, I have gone down the painful but oh-so-typical road of coming from an imperative object- oriented background and trying to build bridges from the patterns learned there to a completely, absolutely different functional world. The problem with this is, your brain works against you (do read the classic Thinking, Fast and Slow (https://www.amazon.com/dp/ B00555X8OA/) by Dr. Kahneman if you haven’t yet – at the very least, it will help you detect and fight your own biases).
Page
16
xx Our brain’s “System 1” works in patterns. It is efficient, extremely fast – much faster than the conscious “System 2,” which we are using when studying Category Theory – it is in contrast subconscious, and it deconstructs and shreds all the elephants you see in your life into basic shapes and curves and colors, which makes recognizing elephants a very easy task, until one day you glimpse upon a fluffy cloud and your brain goes: “Oh, look, it’s an elephant!” Well, no, it’s a cloud. And this is exactly the trap laid out for programmers trying to escape to the wonderful world of Haskell from the less elegant Java, C++, or those terrible-which-shall-not-be-named-but-end-in-…avaScript backgrounds. The thought goes: C++ is a programming language, as is Haskell, so the concepts should be pretty similar, right? Isn’t it like Indian and African elephants? Sure, one has bigger ears, but aren’t they essentially the same? No, they are not: one is an elephant, and the other one is a cloud. You cannot reason about clouds using your elephant knowledge. You can ride an elephant, but attempting to ride a cloud would end really badly. Your brain constantly tries to find analogies between your previous experience and new knowledge – that's how we learn, it is a good thing – but in this case the unfortunate fact that both Haskell and JavaScript are called "programming languages" is a disservice, as trying to find similar patterns in both leads to consequences only slightly less disastrous than trying to ride a cloud thinking it's an elephant. To master the power of Haskell, you need to set aside everything you know about imperative programming and build upon a totally different foundation. One of pure abstract math, starting from Category Theory, from set theory, from Type Theory, from Henri Poincare. You have to build natural numbers with pen and paper starting with an empty set, construct a Ring on them, abstract away and discover Monoids, start appreciating the beauty of the internal structure of types and categories manifested in polymorphic functions and laws on them, be amazed at how one abstraction can elegantly describe seemingly unrelated entities … How THIs book Came To be: InsTead of an InTroduCTIon
Page
17
xxi But who in the world has time for this?! Well, exactly. This is one of the primary reasons there’s still a certain bias against Haskell among practitioners – a big part of the Haskell community give the impression of very smart monad-stacking-arrow- composing-scientist-magicians sitting in their ivory towers with too much time on their hands working out some abstract problems, while we need to code stuff that works even if it’s ugly. I have been using Haskell both in production and hobbyist projects for over 15 years now. Currently we are building an AI agents platform using Haskell as an integral part, so what I would like to say is: take heart, there’s hope! But before I outline a proposed (yet another) way out, let me illustrate the elephant vs. cloud conundrum with a pretty typical “Where is my for loop?!” situation. Let’s say you are building a GUI library based on some low-level API and need to render lines of text on the screen. You construct an array of textures where each corresponds to a new line of text and need to render each one under the other, incrementing a y coordinate, like so: int y = 100; int step = 40; for (int i = 0; i < numOfTextures; i++) { renderTexture (texture[i], y); y += step; } Something you’ve done a thousand times in different situations. You switch to Haskell where you have a list of textures textures :: [Texture], and your System 1 starts screaming “Where is my for loop?!” and then “How do I pass the state when iterating?” Should I use mutable variables, IORef, MVar, TVar? I know I am supposed to map over lists, so should I use a State monad to increment y while mapping? How THIs book Came To be: InsTead of an InTroduCTIon
Page
18
xxii And only when you tell your System 1 to stop getting ideas from your imperative experience, consider abstractions, realize it is best to fold and traverse structures in the functional world, you come to something like foldM (iterate step) startingY textures where iterate s y tex = renderTexture tex y >> (y + s) …which gives you goosebumps after all the braces and semicolons in the C-land, but patterns have nothing in common: you iterate over arrays with mutable variables in one, and you fold structures with computations in the other. Elephants and clouds. So how do we teach Haskell to kids or help adults master its power faster and more efficiently? First, stop trying to build bridges from the imperative world – it messes with people's brains. In fact, explaining design patterns for program architecture on the real-world problems and contrasting approaches with the imperative world is very much needed and largely missing now. However, this needs to be done only after a student has learned the functional approach and small patterns from scratch. Teaching Haskell in the bottom-up imperative way, with "Hello World" and calculator in ghci, is in my strong opinion absolutely counterproductive – it leads right into the elephants vs. clouds trap and takes much longer for the student to start appreciating the power and beauty of Haskell. We need to start from Type Theory, make people understand and fall in love with types, their structure, their daily lives, their relations with each other; a student has to become fluent in writing and understanding type- level functions before they even think about writing “real” functions or “Hello World” for that matter. It is actually a pretty traveled road as well – but only if you have a reasonably strong math background. Catch up on your Category Theory reading (Bartosz Milewski’s Category Theory for Programmers is out and it’s excellent), study Typeclassopedia (https://wiki.haskell.org/Typeclassopedia), use the amazing Stephen Diehl’s What I Wish I Knew When Learning Haskell How THIs book Came To be: InsTead of an InTroduCTIon
Page
19
xxiii (http://dev.stephendiehl.com/hask/) as a reference, and get a feeling on how to structure real programs using monad transformer stacks, but whatever you do, under any circumstances, DO NOT read monad tutorials! Monads are very simple, it’s just another beautiful and powerful math abstraction, one among many, and you will confuse and break your brain with false analogies if you read the tutorials – study it in the context of Functor–Applicative–Monad hierarchy, so, again, Typeclassopedia, or, of course and hopefully, this book. Then, what was the point of all this? I am a very visual person when studying, and I've been thinking for some time now that math concepts underlying modern functional programming and Type Theory can be explained in a more accessible way using visuals, magic, and various cute animal-related analogies. Existing literature on the concepts mentioned above is often too technical, even for practicing programmers, let alone kids, even in their teens, and focuses on formal proofs a lot. However, if we ease on trying to rigorously prove stuff and just illustrate and explain those same concepts, from lambda calculus in SystemFw (even the name is a mouthful, but the machinery is again extremely simple!) to types and their relations to Category Theory and arrows, in a top-down visual approach, this may help people build new patterns, which are completely unrelated to imperative programming. Then gradually move to a more technical, more in-depth study while already becoming productive in writing elegant Haskell code for practical tasks. Something in the spirit of excellent "Learn you a Haskell" (learnyouahaskell.com) but building up upon the math foundation of types and typeclass hierarchy vs. “Hello World” and ghci REPL. Hence, the idea of Magical Haskell was born. In fact, it should probably go well hand in hand with Learn You a Haskell for Great Good! – with the latter providing for a lot of basic language foundation in much more detail and Magical Haskell focusing on trying to create a system of typed functional patterns, typeclass hierarchy, and explaining abstract technical concepts in an accessible comprehensible way. How THIs book Came To be: InsTead of an InTroduCTIon
Page
20
xxiv Short Introduction: How to Read This Book In this book, we make an attempt to introduce advanced and at times very technical concepts that underlie Haskell language in an accessible way, using everyday analogies, pictures, and real-world examples where possible. We have a strong conviction that having a strong grasp on types and the bigger picture, in general, makes any practical Haskell programmer much more efficient and productive while also being able to fully appreciate the beauty of the mathematical concepts involved. We start with these foundations and then move to the advanced concepts of how to structure real-world big applications (a topic a lot of Haskell students struggle with) using a variety of abstractions, libraries, and design patterns. We start Chapter 1 with basic types and functions, introducing the functional approach to solving problems along the way. Chapter 2 continues with an introduction to algebraic data types, parametric types ("type functions"), recursion, and pattern match. We also look at a concise program that deals with a deck of cards and uses a lot of these concepts. At the end of this chapter, we "invent" a Functor. Chapter 3 focuses on a semiformal introduction to the (Martin-Loef) Type Theory and very lightly touches on Category Theory. Haskell uses a weaker type system called "System FC," but again, understanding the bigger picture helps to both grasp Haskell abstractions and transition to languages such as Idris or Coq with less difficulty. Chapter 4 focuses on basic typeclasses using ubiquitous algebraic examples (such as Monoid) to explain the concept. Chapter 5 follows up with and focuses on how to introduce Functor and Bifunctor naturally and finishes with Applicative discussion, a further specialization of the Functor. In Chapter 6, we gently introduce Monads, showing again how they naturally extend the Functor–Applicative–Monad triad, and discuss three most popular monad types: Reader, Writer, and State. Chapter 7 discusses the IO Monad, introduces “do notation,” and explains what How THIs book Came To be: InsTead of an InTroduCTIon