News aggregator

extensible effects + classy lenses

haskell-cafe - Wed, 03/09/2016 - 1:59am
Hi all, I'm trying to combine an extensible effects style state with classy lenses. That is, instead of pinning the type of my state down, I'd like to only require the pieces I need. For example, {-# language FlexibleContexts #-} import Control.Monad.Freer import Control.Monad.Freer.State class HasInt s where getInt :: s -> Int foo :: (Member (State s) effs, HasInt s) => Eff effs Int foo = get However, this fails to typecheck: Overlapping instances for Member (State s0) effs Matching givens (or their superclasses): (Member (State s) effs) bound by the type signature for foo :: (Member (State s) effs, HasInt s) => Eff effs Int at example.hs:9:8-56 Matching instances: instance Data.Open.Union.Member' t r (Data.Open.Union.FindElem t r) => Member t r -- Defined in ‘Data.Open.Union’ (The choice depends on the instantiation of ‘effs, s0’) In the ambiguity check for the type signature for
Categories: Offsite Discussion

Functional Jobs: Software Engineer at Purple (Full-time)

Planet Haskell - Wed, 03/09/2016 - 12:38am

Purple is a well-funded startup of about 15 people, backed by an Uber co-founder, and revolutionizing the way people get gas.

We are looking for an experienced Software Engineer who can thrive in a startup environment to help us continue to build and test our backend web service and mobile app platform. You would work closely with our small engineering team in a relatively flat organizational structure. You should be confident taking ownership of your specific piece of the product while being comfortable reaching across the full stack. We want people who are aware of latest trends and know how to adopt the most appropriate technology. We're looking for someone who is a strong advocate for the best engineering practices.

Most of our codebase is written in Clojure and ClojureScript. While prior Clojure experience is not a requirement, serious candidates must have an interest and willingness to learn Clojure as well as any technologies we are using that they may not currently be familiar with.

Minimum qualifications:

  • BS degree in Computer Science, similar technical field of study or equivalent practical experience.
  • Strong experience in one or more general purpose programming languages
  • Strong experience in at least one scripting language (e.g., JavaScript)
  • Interest and ability to learn new programming languages as needed
  • Working knowledge of Git
  • Ability to communicate with non-technical team members to meet product needs/goals

A big plus, but not required:

  • Experience using React and React Native
  • Clojure and ClojureScript experience, or:
  • Experience in at least one functional programming language (Scala, OCaml, Lisp, Haskell, etc.)
  • Familiarity with the JVM and related tooling

Purple is a great team! We are small, savvy, and fun. We have an office based in Westwood. We offer a competitive salary, flexible work schedule, health insurance supplement, and unlimited vacation. Come join our growing team!

Get information on how to apply for this position.

Categories: Offsite Blogs

Implement traverseMaybe in Data.Map, Data.IntMap, etc

libraries list - Tue, 03/08/2016 - 10:43am
As far as I know, the most general form of a function that allows traversing and filtering is: type Filter s t a b = foall f. Applicative f => (a -> f (Maybe b)) -> s -> f t In my witherable[0] package, I defined `Witherable` as a subclass of `Traversable` to provide such operation for various containers. class T.Traversable t => Witherable t where wither :: Applicative f => (a -> f (Maybe b)) -> t a -> f (t b) ... However, the `wither` for `Map` is currently inefficient because it is defined in terms of `traverse` and `mapMaybe`, so it traverses the container twice. Efficient implementation.would have to use the hidden constructors. I would like to propose adding `traverseMaybe` and `traverseMaybeWithKey` for `Data.Map`, `Data.IntMap`, and their strict variants (I'm suggesting more conservative name because wither might sound too unusual or poetic for a standard library. I like 'wither' though). A possible implementation would be like this: traverseMaybeWithKey :: Applicative f => (k -> a ->
Categories: Offsite Discussion

Well-Typed.Com: Haskell development jobs with Well-Typed

Planet Haskell - Tue, 03/08/2016 - 10:24am

tl;dr If you’d like a job with us, send your application as soon as possible.

We are looking for several (probably two) Haskell experts to join our team at Well-Typed. This is a great opportunity for someone who is passionate about Haskell and who is keen to improve and promote Haskell in a professional context.

About Well-Typed

We are a team of top notch Haskell experts. Founded in 2008, we were the first company dedicated to promoting the mainstream commercial use of Haskell. To achieve this aim, we help companies that are using or moving to Haskell by providing a range of services including consulting, development, training, and support and improvement of the Haskell development tools. We work with a wide range of clients, from tiny startups to well-known multinationals. We have established a track record of technical excellence and satisfied customers.

Our company has a strong engineering culture. All our managers and decision makers are themselves Haskell developers. Most of us have an academic background and we are not afraid to apply proper computer science to customers’ problems, particularly the fruits of FP and PL research.

We are a self-funded company so we are not beholden to external investors and can concentrate on the interests of our clients, our staff and the Haskell community.

About the jobs

One of the roles is for a specific project with one of our clients, and requires work on-site in London. The other role is more general and not tied to a single specific project or task, and allows remote work.

Please indicate in your application whether on-site work in London is an option for you.

In general, work for Well-Typed could cover any of the projects and activities that we are involved in as a company. The work may involve:

  • working on GHC, libraries and tools;

  • Haskell application development;

  • working directly with clients to solve their problems;

  • teaching Haskell and developing training materials.

We try wherever possible to arrange tasks within our team to suit peoples’ preferences and to rotate to provide variety and interest.

Well-Typed has a variety of clients. For some we do proprietary Haskell development and consulting. For others, much of the work involves open-source development and cooperating with the rest of the Haskell community: the commercial, open-source and academic users.

Our ideal candidate has excellent knowledge of Haskell, whether from industry, academia or personal interest. Familiarity with other languages, low-level programming and good software engineering practices are also useful. Good organisation and ability to manage your own time and reliably meet deadlines is important. You should also have good communication skills. Being interested or having experience in teaching Haskell (or other technical topics) is a bonus. Experience of consulting or running a business is also a bonus. You are likely to have a bachelor’s degree or higher in computer science or a related field, although this isn’t a requirement.

Offer details

The offer is initially for one year full time, with the intention of a long term arrangement. For the remote role, living in England is not required. For the on-site role, you have to be allowed to work in England. We may be able to offer either employment or sub-contracting, depending on the jurisdiction in which you live.

If you are interested, please apply via Tell us why you are interested and why you would be a good fit for Well-Typed, and attach your CV. Please indicate whether the on-site work in London is an option for you. Please also indicate how soon you might be able to start.

We are more than happy to answer informal enquiries. Contact Duncan Coutts (, dcoutts on IRC), Adam Gundry (, agundry on IRC) or Andres Löh (, kosmikus on IRC) for further information.

We will consider applications as soon as we receive them, and will try to fill the positions as soon as possible. In any case, please try to get your application to us by March 27, 2016.

Categories: Offsite Blogs

Use cases of empty type classes

haskell-cafe - Tue, 03/08/2016 - 8:10am
Hi everyone, I have one question. What are current use cases of type classes with no methods? I saw early uses in type-level programming (e.g. HList [1]). In the OO world, interfaces with no methods are called marker interfaces -- their use cases range from things that could be done with datatype generic programming in Haskell (e.g. serialization) to metadata annotations (e.g. RandomAccess [2]). Regards, Tomas Tauber [1] [2]
Categories: Offsite Discussion

Add `take`/`drop`/`splitAt` to `Data.Map`/`Data.Set`

libraries list - Tue, 03/08/2016 - 2:14am
I would like to propose adding `take`/`drop`/`splitAt` to both `Data.Map` and `Data.Set` as originally requested in: <> The motivation behind this proposal is three-fold: * for convenience - these functions are commonly used to implement pagination or previews of maps/sets * for type accuracy - the public API impose an unnecessary `Ord` constraint * for efficiency - these can be implemented more efficiently using the internal API Currently the only way you can implement this functionality via the public API is to use `lookupIndex`/`elemAt` + `split`. For example, one way to implement `Data.Set.take` is: take :: Ord a => Int -> Set a -> Set a take n m | n < 0 = empty | size m <= n = m | otherwise = lt where (lt, _) = split k m k = elemAt n m {-# INLINE take #-} This implementation incurs an unnecessary `Ord` constraint due to a roundabout way of computing `take`: this ext
Categories: Offsite Discussion

implicit call stacks and calling function

haskell-cafe - Mon, 03/07/2016 - 9:35pm
I noticed this when I started using the new implicit call stacks feature. I didn't bring it up because I figure it probably had a good reason and was too late to change anyway, but the recent talk about HasCallStack reminded me and I'm curious. When you do GHC.Stack.getCallStack you get a [(String, SrcPos)]. The SrcPos is the position of the calling function, but the String is the callee function. So you can't get the name of the calling function. Instead, you get the name of the function with the call stack annotation. That's not so useful because in say a logging function, I'm interested in the caller's name. I don't need the name of the logging function, it's just something boring like "info" or "warn"! When I switched from a custom preprocessor that sort of implemented SRCLOC_ANNOTATE, it was definitely nice to lose the custom local hackery, but not so nice to lose the caller's name. For tests I used an unsafe mutable global via unsafePerformIO, otherwise failed tests can't report the name of the
Categories: Offsite Discussion

[ANN] brick-users discussion list

General haskell list - Mon, 03/07/2016 - 7:56pm
Hi, If you use the 'brick' library then you might like to know that there is now a library discussion list for it:
Categories: Incoming News

Magnus Therning: Final version of JSON to sum type

Planet Haskell - Mon, 03/07/2016 - 6:00pm

After some feedback on my previous post I ended up with the following implementation.

instance FromJSON V.VersionRange where parseJSON = withObject "VersionRange" go where go o = V.thisVersion <$> o .: "ThisVersion" <|> V.laterVersion <$> o .: "LaterVersion" <|> V.earlierVersion <$> o .: "EarlierVersion" <|> V.WildcardVersion <$> o .: "WildcardVersion" <|> nullaryOp V.anyVersion <$> o .: "AnyVersion" <|> binaryOp V.unionVersionRanges <$> o .: "UnionVersionRanges" <|> binaryOp V.intersectVersionRanges <$> o .: "IntersectVersionRanges" <|> V.VersionRangeParens <$> o .: "VersionRangeParens" nullaryOp :: a -> Value -> a nullaryOp = const binaryOp f [a, b] = f a b

Thanks David for your suggestions.

Categories: Offsite Blogs

Tagged instances for Aeson overlapped

haskell-cafe - Mon, 03/07/2016 - 4:37pm
Hello, I tried to compile my project with GHC 8 (from HEAD). And I got One of instances should be removed probably. I suppose that instance for removing should be instance in Data.Tagged. But version in Aeson should be PolyKinded. What do you think? Best regards, Dmitry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe< at >
Categories: Offsite Discussion

Trouble on Travis CI with recent cabal versions

haskell-cafe - Mon, 03/07/2016 - 10:19am
For my OpenGLRaw project, I'm using a .travis.yml generated by Herbert's and the corresponding PPA. Recently things broke on Travis CI, and there are a few strange things: * The cabal-install-head package seems to be based on cabal 1.23, which is older than cabal-install-1.24. Is this intended? * The OpenGLRaw package has no test suite, and this seems to be OK for cabal-install-head (, while cabal-install-1.24 fails in the "cabal test" step ( This is a regression: I think that "cabal test" for a package without a test suite should be a no-op, at least that used to be the case. * Why does "cabal test" say "Re-configuring with test suites enabled. If this fails, please run configure manually." when "cabal configure" has already been run (including --enable-tests)? This looks li
Categories: Offsite Discussion

1-to-many preprocessor in stack/Cabal builds

haskell-cafe - Mon, 03/07/2016 - 8:53am
Hi, I'm writing a package which uses custom preprocessor for creating some of the source files. It takes one IDL file as input and writes several .hs modules, depending on IDL contents. I need to compile this modules with a few normal ones and link them as a library, preferably with generated modules exposed. It doesn't look like a complex task and never was in with make/etc, but I run into some problems now. Obviously, cabal supports 1-to-1 preprocessors to create one Haskell module from one source file (alex, happy, etc), but I can't find anything for 1-to-many preprocessors. So, I decided to use hookedPrograms and hooks and do it myself. The call to preprocessor in the postConf hook worked just fine and created source files and module list. Cabal pre-* hooks seems to be right place to read this module list and use it, but are presenting two problems: can only modify other-modules, not exposed-modules, which is tolerable, and there is no access to build configuration. The latter is fatal, I need to know
Categories: Offsite Discussion

PolyKind for Fixed and HasResolution from Data.Fixed

haskell-cafe - Sun, 03/06/2016 - 7:29pm
Hi all! If we define HasResolution and Fixed like that: class HasResolution (a :: k) where resolution :: p a -> Integer newtype Fixed (a :: k) = Fixed Integer We can do something like that: instance KnownNat a => HasResolution a where resolution = natVal 2.3 :: Fixed 1
Categories: Offsite Discussion

GADTs and Exponentiated Functors

haskell-cafe - Sun, 03/06/2016 - 2:11pm
Hi, I have been recently playing around with GADTs, using them to keep track of how many times a functor has been applied. This provides a solution to what seems to be a long standing problem, summarized here: If the nesting depth is part of the type, it is possible to apply fmap automatically as needed. This allows you to write fairly elegant expressions like: data Person = Person { name :: String, age :: Integer, gender :: String, status :: String } deriving Show let persons = fromList' [Person {name="Alice", age=20, gender="F", status="Good"}, Person {name="Bob", age=18, gender="M", status="Good"}, Person {name="Chuck", age=16, gender="M", status="Bad"}] :: NList N1 Person persons `select` age
Categories: Offsite Discussion

Philip Wadler: The Ask

Planet Haskell - Sun, 03/06/2016 - 9:40am
Scottish elections take place on 5 May 2016.

The Scottish Government have set a target of 10% of all trips by foot or bicycle, but less than 2% of the Scottish travel budget goes to 'active travel' (the buzzword for getting from one place to another minus a motor). We Walk, We Cycle, We Vote and Spokes suggest you ask your candidate to pledge the following:
To raise the share of the transport budget spent on walking and cycling to 10% over the course of the next parliament.See the pages linked above for more info, including hustings you can attend to put the question to your local candidates. A don't forget to Pedal on Parliament on 23 April 2016.

Categories: Offsite Blogs

Type-level list "elem" inference

haskell-cafe - Sat, 03/05/2016 - 9:34pm
So I've got some code that looks like: {-# LANGUAGE DataKinds, UndecidableInstances, TypeFamilies, KindSignatures, TypeOperators #-} import Data.Proxy import GHC.TypeLits type family IsSubset (as :: [Symbol]) (bs :: [Symbol]) where IsSubset as bs = IsSubsetPrime as bs bs type family IsSubsetPrime (as :: [Symbol]) bs bs' where IsSubsetPrime as '[] bs' = 'False IsSubsetPrime '[] bs bs' = 'True IsSubsetPrime (a ': as) (a ': bs) bs' = IsSubsetPrime as bs' bs' IsSubsetPrime (a ': as) (b ': bs) bs' = IsSubsetPrime (a ': as) bs bs' This lets me write functions like: foo :: (IsSubset '["foo", "bar"] args ~ 'True) => Proxy args -> Int foo args = undefined I've also got a type family: type family IsElem (a :: Symbol) (bs :: [Symbol]) where IsElem a (a ': bs) = 'True IsElem a (b ': bs) = IsElem a bs IsElem a '[] = 'False This lets me write functions like: bar :: (IsElem "foo" args ~ 'True) => Proxy args -> Int bar args = undefined The problem comes when I want to use "bar args"
Categories: Offsite Discussion

Gabriel Gonzalez: From mathematics to map-reduce

Planet Haskell - Sat, 03/05/2016 - 9:24pm

There's more mathematics to programming than meets the eye. This post will highlight one such connection that explains the link between map-reduce and category theory. I will then conclude with some wild speculation about what this might imply for future programming paradigms.

This post assumes that you already know Haskell and explains the mathematics behind the map-reduce using Haskell concepts and terminology. This means that this post will oversimplify some of the category theory concepts in order to embed them in Haskell, but the overall gist will still be correct.

Background (Isomorphism)

In Haskell, we like to say that two types, s and t, are "isomorphic" if and only if there are two functions, fw and bw, of types

fw :: s -> t
bw :: t -> s

... that are inverse of each other:

fw . bw = id
bw . fw = id

We will use the symbol ≅ to denote that two types are isomorphic. So, for example, we would summarize all of the above by just writing:

s ≅ t

The fully general definition of isomorphism from category theory is actually much broader than this, but this definition will do for now.

Background (Adjoint functors)

Given two functors, f and g, f is left-adjoint to g if and only if:

f a -> b ≅ a -> g b

In other words, for them to be adjoint there must be two functions, fw and bw of types:

fw :: (f a -> b) -> (a -> g b)
bw :: (a -> g b) -> (f a -> b)

... such that:

fw . bw = id
bw . fw = id

These "functors" are not necessarily the same as Haskell's Functor class. The category theory definition of "functor" is more general than Haskell's Functor class and we'll be taking advantage of that extra generality in the next section.

Free functors

Imagine a functor named g that acted more like a type-level function that transforms one type into another type. In this case, g will be a function that erases a constraint named C. For example:

-- `g` is a *type-level* function, and `t` is a *type*
g (C t => t) = t

In other words, g "forgets" the C constraint on type t. We call g a "forgetful functor".

If some other functor, f is left-adjoint to g then we say that f is the "free C" (where C is the constraint that g "forgets").

In other words, a "free C" is a functor that is left-adjoint to another functor that forgets the constraint C.

Free monoid

The list type constructor, [], is the "free Monoid"

The "free Monoid" is, by definition, a functor [] that is left-adjoint to some other functor g that deletes Monoid constraints.

When we say that g deletes Monoid constraints we mean that:

g (Monoid m => m) = m

... and when we say that [] is left-adjoint to g that means that:

[] a -> b ≅ a -> g b

... and the type [a] is syntactic sugar for [] a, so we can also write:

[a] -> b ≅ a -> g b

Now substitute b with some type with a Monoid constraint, like this one:

b = Monoid m => m

That gives us:

[a] -> (Monoid m => m) ≅ a -> g (Monoid m => m)

... and since g deletes Monoid constraints, that leaves us with:

[a] -> (Monoid m => m) ≅ a -> m

The above isomorphism in turn implies that there must be two functions, fw and bw, of types:

fw :: ([a] -> (Monoid m => m)) -> (a -> m)
bw :: (a -> m) -> ([a] -> (Monoid m => m))

... and these two functions must be inverses of each other:

fw . bw = id
bw . fw = id

We can pull out the Monoid constraints to the left to give us these more idiomatic types:

fw :: (Monoid m => [a] -> m)) -> (a -> m)
bw :: Monoid m => ( a -> m) -> ([a] -> m)

Both of these types have "obvious" implementations:

fw :: (Monoid m => [a] -> m)) -> (a -> m)
fw k x = k [x]

bw :: Monoid m => (a -> m) -> ([a] -> m)
bw k xs = mconcat (map k xs)

Now we need to prove that the fw and bw functions are inverse of each other. Here are the proofs:

-- Proof #1
fw . bw

-- eta-expand
= \k -> fw (bw k)

-- eta-expand
= \k x -> fw (bw k) x

-- Definition of `fw`
= \k x -> bw k [x]

-- Definition of `bw`
= \k x -> mconcat (map k [x])

-- Definition of `map`
= \k x -> mconcat [k x]

-- Definition of `mconcat`
= \k x -> k x

-- eta-reduce
= \k -> k

-- Definition of `id`
= id

-- Proof #2
bw . fw

-- eta-expand
= \k -> bw (fw k)

-- eta-expand
= \k xs -> bw (fw k) xs

-- Definition of `bw`
= \k xs -> mconcat (map (fw k) xs)

-- eta-expand
= \k xs -> mconcat (map (\x -> fw k x) xs)

-- Definition of `fw`
= \k xs -> mconcat (map (\x -> k [x]) xs)

-- map (f . g) = map f . map g
= \k xs -> mconcat (map k (map (\x -> [x]) xs))

-- ... and then a miracle occurs ...
-- In all seriousness this step uses a "free theorem" which says
-- that:
-- forall (k :: Monoid m => [a] -> m) . mconcat . map k = k . mconcat
-- We haven't covered free theorems, but you can read more about them
-- here:
= \k xs -> k (mconcat (map (\x -> [x]) xs)

-- This next step is a proof by induction, which I've omitted
= \k xs -> k xs

-- eta-reduce
= \k -> k

-- Definition of `id`
= idMap reduce

Let's revisit the type and implementation of our bw function:

bw :: Monoid m => (a -> m) -> ([a] -> m)
bw k xs = mconcat (map k xs)

That bw function is significant because it is a simplified form of map-reduce:

  • First you "map" a function named k over the list of xs
  • Then you "reduce" the list using mconcat

In other words, bw is a pure "map-reduce" function and actually already exists in Haskell's standard library as the foldMap function.

The theory of free objects predict that all other functions of interest over a free object (like the free Monoid) can be reduced to the above fundamental function. In other words, the theory indicates that we can implement all other functions over lists in terms of this very general map-reduce function. We could have predicted the importance of "map-reduce purely from the theory of "free Monoids"!

However, there are other free objects besides free Monoids. For example, there are "free Monads" and "free Categorys" and "free Applicatives" and each of them is equipped with a similarly fundamental function that we can use to express all other functions of interest. I believe that each one of these fundamental functions is a programming paradigm waiting to be discovered just like the map-reduce paradigm.

Categories: Offsite Blogs

Magnus Therning: From JSON to sum type

Planet Haskell - Sat, 03/05/2016 - 6:00pm

For a while I’ve been planning to take full ownership of the JSON serialisation and parsing in cblrepo. The recent inclusion of instances of ToJSON and FromJSON for Version pushed me to take the first step by writing my own instances for all external types.

When doing this I noticed that all examples in the aeson docs use a product

data Person = Person { name :: Text , age :: Int }

whereas I had to deal with quite a few sums, e.g. VersionRange. At first I struggled a little with how to write an instance of FromJSON. After quite a bit of thinking I came up with the following, which I think is fairly nice, but I’d really like to hear what others think about it. Maybe I’ve just missed a much simpler way of implementing parseJSON:

instance FromJSON V.VersionRange where parseJSON = withObject "VersionRange" go where go o = do lv <- (o .:? "LaterVersion") >>= return . fmap V.laterVersion tv <- (o .:? "ThisVersion") >>= return . fmap V.thisVersion ev <- (o .:? "EarlierVersion") >>= return . fmap V.earlierVersion av <- (o .:? "AnyVersion") >>= \ (_::Maybe [(Int,Int)]) -> return $ Just V.anyVersion wv <- (o .:? "WildcardVersion") >>= return . fmap V.WildcardVersion uvr <- (o .:? "UnionVersionRanges") >>= return . fmap toUvr ivr <- (o .:? "IntersectVersionRanges") >>= return . fmap toIvr vrp <- (o .:? "VersionRangeParens") >>= return . fmap V.VersionRangeParens maybe (typeMismatch "VersionRange" $ Object o) return (lv <|> tv <|> ev <|> uvr <|> ivr <|> wv <|> vrp <|> av) toUvr [v0, v1] = V.unionVersionRanges v0 v1 toIvr [v0, v1] = V.intersectVersionRanges v0 v1

Any and all comments and suggestions are more than welcome!

Categories: Offsite Blogs

Reducing boilerplate

haskell-cafe - Sat, 03/05/2016 - 3:56pm
Hi, To write FFI bindings, I use c-storable-deriving [1] to automatically derive CStorable instances for many data types (the only difference between Storable and CStorable is that CStorable provides default methods for types that have Generic instances): {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} ... data X = X { fieldStatus :: Vector 24 Word8 , fieldPadding :: Word8 } deriving (Generic, CStorable) However I also need a Storable instance, hence I have to write (the "c*" methods are provided by CStorable): instance Storable X where peek = cPeek poke = cPoke alignment = cAlignment sizeOf = cSizeOf Is there a way to automatically generate this instance for every data that has an instance of CStorable? Ideally, I would like to say once and for all: instance CStorable a => Storable a where peek = cPeek poke = cPoke alignment = cAlignment sizeOf = cSizeOf As I don't think it is currently possible, w
Categories: Offsite Discussion

Digraphs With Text: More flexible than graphs,eager to hear from you

haskell-cafe - Sat, 03/05/2016 - 10:06am
This is a demonstration of DWT, a data structure built from and more flexible than graphs. It is powered by the *wonderful* Functional Graph Library. We beseech your involvement! DWT is open-source and actively seeking co-developers. I would happily trade any and all the privilege of determining tasks, teaching haskell or math, learning anything, and receiving obligations. We surely have much knowledge to trade! Even just a "hey why don't you do [this]!" could be precious to me. This transcript makes tiny digressions about what monads make possible. graph). (0,"0: frog") that expression. None do, because none yet exist. Such contexts offer many possibilities for tracking where you are (the data) and how you got there (also kind of the data, and perhaps enabling a desirable kind of removal of self|redaction). (0,"0: frog") (0,"1: moist") (0,"2: springy") (0,"0: frog") (0,"1: moist") (0,"2: springy") (0,":3 _ #(is a quality of) _") a : to indicate that it is a template, as opposed to the string "_ is a qual
Categories: Offsite Discussion