Giter VIP home page Giter VIP logo

thinking-with-types's Introduction

Thinking with Types

Dedication

I was terrible in English. I couldn't stand the subject. It seemed to me ridiculous to worry about whether you spelled something wrong or not, because English spelling is just a human convention---it has nothing to do with anything real, anything from nature.

Richard P. Feynman

Overview

This repository is all of the original source material for my book Thinking with Types: Type-Level Programming in Haskell. If you're curious about what goes into writing a book, it might be a good place to peruse.

Building this thing is particularly hard; I had to write three separate build tools, and patch a few upstream libraries. You're free to try to figure it out, but I'd suggest just buying a copy instead!

Don't make me regret open-sourcing this.

Commentary

My overarching organizational principle for this book was to make it as hard as possible to fuck up. That meant that code samples should automatically be tested, GHCi sessions should be automated, solutions and exercises should be co-located, and that there is always a clearly defined source of truth for all material.

The result was a joy to write, but remarkably terrible to deal with after the fact. Paying a marginal compile-time cost of 1s per code example is fine on a chapter-by-chapter basis, but my god does it add up when building the entire project.

Doing it in LaTeX was good for the short-term, but turned into an eventual liability. LaTeX is sweet for quickly producing good-looking pdf documents, but it's sort of the worst of all worlds. It's sort of a content-language, and sort of a real programming language, and doesn't force you into either paradigm. As a result, there was lots of weird fiddling in order to get something to look right---without knowing how it really works or without any discipline.

For writing a thesis or a report, this is fine, but the problem is an eternal one: it's not denotational. LaTeX emphasizes how to do it rather than what to do. The difference bites you in the ass when you want to produce an ebook, for example. You can't use LaTeX to produce the ebook, but you also can't not use LaTeX, because you've automated necessary things in its shitty programming environment.

Also, the tooling breaks all the time, seemingly without any sort of discernible reason.

If I were to do this project again, knowing what I know now, I would write the entire book as a series of Haskell modules. I'd use quasiquoters to write inline prose and build meaningful abstractions in a principled, well-understood language. In essence, I'd write a book DSL, and then write interpretations of that into my eventual desired formats.

License

This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

thinking-with-types's People

Contributors

chkl avatar dciug avatar isovector avatar jonathanlorimer avatar jship avatar nashamri avatar sholland1 avatar sourabhxyz avatar tzemanovic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thinking-with-types's Issues

Your sample chapter is the whole book!

Hi Sandy,

Just passing by to let you know there is a problem with the way your sample chapter is set on leanpub. People downloading the free sample will get the whole book. You should fix it so people will only download a single chapter — unless this is done this way by design, in which case, ignore me :)

Allegedly ContT here isn't ContT!

As suggested in the JFP review, my ContT presented here is actually Codensity. I seem to recall being unable to implement callCC, and that's probably why.

Section 2.2 DataKinds - Error in user example

This example causes an error: Multiple declarations of 'User'

data UserType = User | Admin
data User = User {...}

Since DataKinds is turned on, the first declaration is creating a type User in addition to the usual type in the second declaration.

Exercise 1.4 - i transformation is incorrect

Screen Shot 2020-03-25 at 7 26 07PM

Using the table on page 18, and translating (a^b)^c into types, I get (from the outside in):

= (a^b)^c
= c -> (a^b)
= c -> (b -> a)
= c -> b -> a

Whereas it seems the translation you have provided gives (b -> c -> a).

Presumably you were aiming to ensure the types matched curry/uncurry? This may mean your example needs to change a little, because commutivity etc.

Your reply to my email was:

You're right that the naive transformation doesn't produce exactly the same types. It's trivial to give an isomorphism between the two, and I thought I had that as an earlier example, though upon re-reading, it does not appear to be there.

And yes, it's true that the isomorphism is easy for someone who knows how, but it doesn't immediately fall out of the presentation given in the question.

Necessary Extension Missing for 10.2

Need to add {-# LANGUAGE TypeOperators #-} to the necessary extensions at the beginning of 10.2 on pg. 126.

Everything works fine except for MapList pg. 129 and Foldr pg. 130 which depend on a promoted cons operator ': for example:

data FoldR :: (a -> b -> Exp b) -> b -> [a] -> Exp b
type instance Eval' (FoldR _ z '[]) = z
type instance Eval' (FoldR f z (x ': xs)) =
  Eval' (f x (Eval' (FoldR f z xs)))

I would create a PR myself, but I can't figure out how your TeX preamble is pulling code from your Haskell files

EPub & PDF

Would it be possible to have EPub and PDF releases instead of the source code?

Love the book. Thanks a lot for writing it!

makePropertyObj code does not work and left undefined, 13.3. USING GENERIC METADATA, page 183

Hi,
I tried the code for makePropertyObj at 13.3. USING GENERIC METADATA, page 183
it gives type error. Also checked the code on github it is left as undefined

the original code is (shown as on the book)

makePropertyObj :: forall name . (KnownSymbol name) => Value -> Value
makePropertyObj v = object [pack (symbolVal $ Proxy @name) .= v ]

I noticed the error was due to Haskell could not infer the type as Key from the code pack (symbolVal $ Proxy @name) and was giving below error (which worked for makeTypeObj function)

• Couldn't match expected type ‘Key’ with actual type ‘Text’
• In the first argument of ‘(.=)’, namely
    ‘pack (symbolVal $ Proxy @name)’
  In the expression: pack (symbolVal $ Proxy @name) .= v
  In the first argument of ‘object’, namely
    ‘[pack (symbolVal $ Proxy @name) .= v]’typecheck(-Wdeferred-type-errors)

I made some small changes and Key to import list from aeson package also used fromText and imported Data.Aeson.Key (fromText) and used fromText to convert Text to key and it works i believe if it is the intent;

here is the slightly modified code;

makePropertObj :: forall name . KnownSymbol name => Value -> Value
makePropertObj v = object [fromText (pack (symbolVal $ Proxy @name)) .= v ]

and just did a quick check on it if it works as it is

-- >>>makePropertObj @"age" (makeTypeObject @Int)
-- Object (fromList [("age",Object (fromList [("type",String "integer")]))])

also the changes on the import list I made ;

import Data.Aeson (Value (..), (.=), object, Key)
import Data.Aeson.Key (fromText)

Color print

This seems like the perfect book I would like to read. Except the print version on Lulu is listed as "Interior Ink Black & white". Is there no color for code highlighting in the print version?

Existential Type Elimination Aliases Break Example

In section 7.1.2 it is mentioned that we can generalize the pattern of creating existential constraint kinds by implementing Has and creating type aliases for HasShow and Dynamic in terms of it.

However no further mention is given to how the code from the prior example should be updated since removing the data constructors breaks liftD2 and the prior elimHasShow and elimDynamic functions. It would be cool to show how to update the prior code so that it compiles again or, if appropriate skills have been learned, to make it an exercise to fix it.

No chapter 2 in sample chapters

Hi there, I downloaded the samples today and have started reading it - it's interesting so far!

However I was confused when I went from Chapter 1 to Chapter 3. I checked the ToC and sure enough it also goes from 1 to 3. I was wondering if Chapter 2 is elided from the samples on purpose, or if it's a bug, or an easter egg, or...?

Also, I couldn't find a ToC on the website or LuLu to try to work out which of the above was the issue.

Thanks again, hope it goes well!

EPUB formatting on leanpub

Can you have a look at the formatting of the epub on leanpub? The math images (Latex, I guess) are completely out of proportion. The 1234 blobs that enumerate code lines are a good idea, but they don't work at all in the epub because of their large size.
IMHO the epub is unreadable. Pleeeez fix!

formatting of epub

2.2 Data Kinds: the code on page 29 will not work as is

Page 29 defines a data type to be used as a data kind:

data UserType
  = User
  | Admin

Then suggests to refine some User data type:

data User = User { ... }

Unfortunately, the two cannot coexist as is, since they use the same data constructor name User. Seasoned Haskellers will not be too bothered by this, but someone a little new can be surprised by the duplicate identifier error.

(Mediocre) suggestions for fixes:

  • renaming User into something else in UserType... nothing great comes to mind, the somewhat verbose NormalUser? :\
  • explicitly mentioning that UserType should live in its own module and used qualified as UserType.User?

Not sure, it's a very minor issue! :-)

Issues getting code from OpenSums to compile

Relevent pages 138-141

import Fcf is not found, and if you get rid of that you are hit with other errors when you implement

type FindElem (key :: k) (ts :: [k])
   = FromMaybe Stuck =<< FindIndex (TyEq key) ts

there are three errors:

 error:
    Not in scope: type constructor or class ‘Stuck’
   |
33 |    = FromMaybe Stuck =<< FindIndex (TyEq key) ts
   |                ^^^^^
/Users/jonathan.l/Documents/thinking-with-types/src/CH11.hs:33:22-24: error:
    Not in scope: type constructor or class ‘=<<’
   |
33 |    = FromMaybe Stuck =<< FindIndex (TyEq key) ts
   |                      ^^^
/Users/jonathan.l/Documents/thinking-with-types/src/CH11.hs:33:26-34: error:
    Not in scope: type constructor or class ‘FindIndex’
   |
33 |    = FromMaybe Stuck =<< FindIndex (TyEq key) ts
   |                          ^^^^^^^^^

Additional required typeclasses for 15.4

Additional typeErrors indicated the need for

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE StandaloneDeriving #-}

to be enabled before the singletons definition quasiquoter would compile.

just a heads up

Minor bugs in CH5 GADTs

Require proper Eq instance for Ord instance to work

For exercise 5.3-iii you need to have the Eq instance for HList defined in terms of All. This is because the tail of HList needs an Eq instance as well as the whole thing when defining the Ord instance:

this will work

instance All Eq ts => Eq (HList ts) where
  HNil == HNil = True
  (a :# as) == (b :# bs) = a == b && as == bs

instance (All Eq ts, All Ord ts) => Ord (HList ts) where
  compare HNil HNil = EQ
  compare (a :# as) (b :# bs) = compare a b <> compare as bs

this will not work

instance Eq (HList '[]) where
  HNil == HNil = True

instance (Eq t, Eq (HList ts)) => Eq (HList (t ': ts)) where
  (a :# as) == (b :# bs) = a == b && as == bs

instance (All Eq ts, All Ord ts) => Ord (HList ts) where
  compare HNil HNil = EQ
  compare (a :# as) (b :# bs) = compare a b <> compare as bs

Typo in solutions

Solution for exercise 5.3-ii on pg 249:

currently is

instance (Show t, Show (HList ts)) => Show (HList (t ': ts)) where
  show (x :# xs) = show x <> ":#" show xs

should be

instance (Show t, Show (HList ts)) => Show (HList (t ': ts)) where
  show (x :# xs) = show x <> ":#" <> show xs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.