Laziness again

I wrote recently about laziness, I was trying to convey a sense of how useful laziness can be. I pointed out that it does have some disadvantages. I have been reading Michael Snoyman’s series of posts on the bad parts of Haskell (part 2, and part 3). It’s part 1, that I’m interested in. He talks about the sum and product functions over lists, here is what he says: The sum and product functions are implemented in terms of foldr. Well, actually foldMap, but list’s foldMap is implemented in terms of foldr, and lists are the only data structure that exist in Haskell. “Oh, but foldr is the good function, right?” Only if you’re folding a function which is lazy in its second argument. + and * are both strict in both of their arguments. ...

February 10, 2021 · Allan Clark

Generating from types

I actually managed to do a little bit of work on the pole-prediction backend last night. There is a part where we store messages in the “database” (it’s not really a database, it’s really just persistent storage). So the messages are a variant type, and as such we need to write code to both encode each message into JSON, and decode each message from JSON. type DatabaseMessage = AddDriver Year Driver | AddTeam Year Team | AddEntrant Driver.Id Team encodeDatabaseMessage : DatabaseMessage -> Encode.Value encodeDatabaseMessage dMsg = case dMsg of AddDriver year driver -> [ ( "tag", "AddDriver" |> Encode.string ) , ( "arg1", year |> Encode.int ) , ( "arg2", driver |> Driver.encode ) ] |> Encode.object AddTeam year team -> [ ( "tag", "AddTeam" |> Encode.string ) , ( "arg1", year |> Encode.int ) , ( "arg2", team |> Team.encode ) ] |> Encode.object AddEntrant year driverId team -> [ ( "tag", "AddEntant" |> Encode.string ) , ( "arg1", driverId |> Encode.string ) , ( "arg2", team |> Team.encode ) ] |> Encode.object databaseMessageDecoder : Decoder DatabaseMessage databaseMessageDecoder = let interpret s = case s of "AddDriver" -> Decode.succeed AddDriver |> Decode.andField "arg1" Decode.int |> Decode.andField "arg2" Driver.decoder "AddTeam" -> Decode.succeed AddTeam |> Decode.andField "arg1" Decode.int |> Decode.andField "arg2" Team.decoder "AddEntrant" -> Decode.succeed AddEntrant |> Decode.andField "arg1" Decode.string |> Decode.andField "arg2" Decode.string _ -> Decode.fail (String.append "Unknown message string: " s) in Decode.field "tag" Decode.string |> Decode.andThen interpret As you can see all of this is very repetitive and lends itself well to being automatically generated. You can easily imagine some meta-code that, given a type definition, can automatically generate an encoder and decoder (there is also the elm-codec library but if you’re auto-generating these anyway then that’s less useful). ...

February 8, 2021 · Allan Clark

Laziness

I have spoken recently about compile-time laziness as well here and here. Both Elm and Purescript are pure languages that in theory could be compiled as a lazy language. Because there are no side-effects laziness wouldn’t change the behaviour of most programs and those that it does, it is because of infinite loops that do not need to be calculated. However both have chosen to compile in eager (or strict) fashion, partly to reduce the complexity of the compiler, and partly to allow easier interop with Javascript which is the target of compilation in both cases. ...

February 7, 2021 · Allan Clark

Typed meta-programming

This post is some vague, not-well-thought-out rambling on meta-programming in statically typed languages. As I have said dynamically typed languages tend to have meta-programming already baked in. This is because changing the program itself, doesn’t need to be re-type checked. However, the whole point of a statically typed language is that the program is type-checked before it is run. So you cannot then change the program at run-time because in that case the new program would not be typed. In theory of course you could allow this, but you would have to do one of three things: ...

February 6, 2021 · Allan Clark

Nested records and defensive programming

A fairly common problem for an Elm developer to encounter after around 6 months is that nested record update is a little painful. Suppose you have a form on your model, like this: type alias CommentForm = { content : String , subject : String , visibleToAll : Bool } type alias Model = { route : Route , commentForm : CommentForm , ... } So now you want to handle the message for updating the comment form. So you might have a handler like this: ...

February 5, 2021 · Allan Clark

Splitting Elm messages

Elm apps, require that we define a single type, usually called Msg, to host the type of messages that form a major part of the ‘The Elm Architecture’. This single type is usually a custom/variant type, and because it must host all of the messages that the app may consume, it can get rather large. This leads to a large update function. I do not think this necessarily a bad thing, but many beginners to Elm baulk at the idea of large functions, and so they seek solutions to break up their Msg type. The basic idea is to make your messages hierarchical, so you have a variant that itself contains a variant. The question is how best to split this up. I’m going to explain why the first instinct in this is usually wrong, suggest a slightly better way, and end up by claiming that the main thing is to remain fluid in your datatypes so that you can best represent whatever the current situation is, rather than cling to an old design for earlier requirements. ...

February 3, 2021 · Allan Clark

Type classes are meta-programming

A feature that is semi-regularly requested in Elm, or at least discussed is the issue of type-classes. Type classes are a means in Haskell of restricting polymorphism, which then allows you to write more generic functions that you would otherwise be able to. In fancy words that means that type classes support ad-hoc polymorphism, but you can forget about that. I’ll start off with a simple example, then show how you could acheive a similar result without the type classes. Finally I’ll use this to argue that therefore type-classes are a limited form of meta-programming. ...

February 2, 2021 · Allan Clark

Could meta-programming be harmful?

Could meta-programming be considered harmful? Probably not, but like all features of programming languages it will not automatically improve your code. Because I intend to talk in some future posts a little about meta-programming in statically typed languages I want to first lay down some caution. In other words, I do not wish for it to be taken as granted that meta-programming is a solid win, a feature that needs to be added to statically typed languages. ...

February 1, 2021 · Allan Clark

Dynamically typed languages and meta-programming

I’m going to go a little nostalgic and explain my journey through thoughts on statically/dynamically typed languages. I’ll arrive at the conclusion that (some) dynamically typed languages have mostly nailed meta-programming. Whilst it still seems something of a todo for statically typed languages. Dynamically/Statically typed languages and productivity When I first started programming, for a while, I was a card-carrying member of the strongly, statically-typed languages fan club. I didn’t really understand why anyone would ever wish to remove type type-checker which I saw as a major help to the programmer. In other words, I couldn’t really understand why anyone would wish to write code that did not pass a static type-checker. ...

January 31, 2021 · Allan Clark

Relative issue prioritising

Update We have started using Constructor which allows us to do exactly this. It doesn’t yet have a ‘public’ issue board, but I believe the developers are working on it. We are a three person team and we use github to store our source code. We also use github to track our issues. There is a missing feature that I’ve never seen in any bug-tracker: relative prioritising of issues. We typically have a meeting after a sprint of work to decide what to work on next. During this meeting we (perhaps after creating some new issues) mark several with the tag “priority”. But what I really want to do, is order the issues by priority. ...

January 29, 2021 · Allan Clark

Immutability bugs

I am a paid up member of the immutability appreciation society. I believe programming in an immutable language reduces bugs, as well as potentially helps the compiler optimise your code (though perhaps at the cost of not being able to do similar optimisations yourself). I also rather suspect that immutability has a role to play in concurrent code, but that’s somewhat irrelevant for today. However, although I feel that immutability reduces bugs, I do not think of it as a strict subset. A strict subset would imply both that, some bugs introduced using a mutable language are simply not possible, or at least less likely when using an immutable language and also there are no bugs introduced using an immutable language that would be impossible or less likely when using a mutable language. It’s the second part I disagree with. I think most immutable programmers know this, but it’s worth reminding ourselves of this. It’s very easy to get comfortable in our land of the fewer bugs. ...

January 23, 2021 · Allan Clark

Cognitive Biases and Programming

I’ve long been interested in psychology. I find it fascinating the ways in which our brain is capable of tricking even ourselves. Even if some results are difficult to re-produce in the real world, the fact that they work in a laboratory setting is interesting enough. I’ve long thought that many cognitive biases have a strong application to software development. If I had the time I’d love to create a catalog of cognitive biases and their particular application to software development. In lieu of that, I’ll settle for blogging about the odd one. ...

January 19, 2021 · Allan Clark

Comments and word-wrap

Since almost as long as compilers have been around there have been attempts to store source code as something other than plain text. Various different formats have been suggested but the actual format is not important the general idea is to store the abstract syntax tree of your program rather than text that can be parsed into the abstract syntax tree of your program. There are several reasons you might wish to do this, and several disadvantages as well. But I wanted to speak today about one particular part of this. Comments. ...

January 15, 2021 · Allan Clark

Delete this comment

This morning someone posted their snake game implementation to the Elm discourse asking for feedback on their implemenation. I thought the implementation was pretty fine, I had one structural comment but for the most part I’d be pretty happy to have to work on something from that code. My complaint though was that the author’s source code comments were mostly pointless, at least none of them were (yet) downright counter-productive, but it’s easy enough for comments to become so. I was reminded of an excellent student of mine who wrote a blog post (as part of their coursework) entitled ‘Delete this comment’ you can find it here. ...

January 11, 2021 · Allan Clark

Defensive programming and validations

Defensive programming is generally defined using terms such as ‘impossible’, one definition on the c2 wiki has Defend against the impossible because the impossible will happen. In addition there is also the idea to do the right thing. Such a definition is obviously (and intentionally) vague. The question is, what is the right thing? That’s always situation specific and it can be a difficult part in programming. That’s what I find interesting here, the programmer can easily make happen whatever we want, but it’s difficult to decide what we should want. That’s difficult to follow so let’s try an example. ...

January 6, 2021 · Allan Clark