Search code examples
haskellhaskell-lens

Why does lens include an Iso for fromEnum/toEnum, but not one for show/read?


Suppose you declare two isomorphisms

showing :: (Read a, Show a) => Iso' String a
showing = iso read show

reading :: (Read a, Show a) => Iso' a String
reading = iso show read

They are unsafe, not every String will parse as an a.

That begs the question: Why those two aren't included in the library if enum = iso fromEnum toEnum is?

It is just as unsafe and can't be prevented by the type system. They all shift the burden onto the programmer who has to ensure that the transformation will not break the isomorphism.

Quick example: under enum (+1) True will throw an exception


Solution

  • Warning: speculative answer follows.

    One difference between the two scenarios I can think of is that it is reasonably easy to clarify when toEnum breaks down (quoting the lens docs: "this is only an isomorphism from the numeric range actually used"), while things are a fair bit murkier when it comes to read. Another difference is that toEnum is a method of Enum (and one required in a minimal instance definition, at that), while read isn't actually a method of Read, and so is, in a sense, less essential (in fact, the base docs explicitly discourage its usage).

    On a more general note, when it comes to choosing between exposing a bullet-proof interface and including useful but potentially unsafe or unlawful combinators, lens usually goes for the latter, making them available for those who wish to use them while acknowleding any potential issues in the documentation (or, in hairier cases, in function and module names). Given that lens is a very general purpose library, this approach can be seen as a non-opinionated choice -- in a context like this, it can be hard to compensate for the absence of combinators.

    P.S.: It is also worth noting that lens encodes read and show through the _Show prism. _Show is equivalent to prism' show readMaybe, and is safe with respect to the partiality of Read-ing values.