The From Project
Welcome to the From Project!
This is a multi-package repo. You may want to see README.md of each package as well.
Synopsis
- Use
from :: a -> bto convert anInt16to aWord32, or aData.Text.Lazy.Builder.Builderto aByteString.- The rule of thumb is, if there is a "sane default way" to convert a type to another type, there should be a
Frominstance for that mapping. - This way, you don't have to memorize every single conversion function like
toStrictByteStringordecodeUtf8Lenient.
- The rule of thumb is, if there is a "sane default way" to convert a type to another type, there should be a
- Use
tryFrom :: a -> Maybe bfor conversions that can fail. - "from" (the core package) has 1 dependency: base.
- "from-string" has 3: base, bytestring, and text.
Usage
The "from" package provides some default instances for the basic integral types.
"from-string" should be useful for nearly all practical Haskell projects. import From.String and use from to convert string types (String, strict ByteString, lazy Bytestring, strict Text, lazy Text, Builder, ...).
Why?
If you are only interested in convenience, you don't need to read on at all. However, if you noticed this is not the first attempt of its kind, you may be wondering how this is a good idea instead of xkcd #927. Let us explain.
Aesthetics and conciseness mattered more than we previously thought
Consider do: If you've been following the Haskell ecosystem for a while, you probably would have noticed how libraries began declaring a Monad instance to types that are not quite Monad. This happens because they want the do notation for something that is, in fact, Semigroup.
They all define a type SomethingM a, and then add a type synonym like type Something = SomethingM (). This way, they can provide primitives that are Something, and these primitives can be composed in a do notation; The library user can simply put one item per line.
someChain = do
a
b
c
Some people suggested adding mdo or be for this. But, after all...
someChain = be
a
b
c
is actually
someChain = mconcat
[ a
, b
, c
]
... and the Haskell Committee was reluctant, because they thought , or [] couldn't possibly be such horrible syntactic noise to grant a new syntax.
But in the meantime, we now see so many packages that do this. cereal does this. lucid does this. shakespeare does this. People love to (ab)use the do notation to express semigroups!
I cautiously suggest that aesthetics is one of the reasons why convertible did not really catch on. It provides convert, and it has these subjective issues:
- The name
convertis long.- I know, this can't possibly be a legitimate reason, but then,
[,]can't possibly be a reason to define a whole set of unnecessaryFunctor,Applicative, andMonadinstances. But people do this! - Consider how
acc(instead ofaccumulator) is a widespread name in Haskell. Usuallyaccis only needed for recursive functions, yet people choose to abbreviate it.convertis needed in far more occasions.
- I know, this can't possibly be a legitimate reason, but then,
convert somethingdoes not sound right.- It's supposed to be a pure function, but in English,
convert somethingmay sound like action, instead of expression. Compareconvert somethingtofrom somethingas "expression."
- It's supposed to be a pure function, but in English,
- We already have the
fromconvention in base:fromIntegral,fromEnum,fromMaybe,fromException,fromString,fromList, ...
Dependencies matter
Type conversion is such a common need, that its typeclass (and functions) should be one of the building blocks for all other projects.
Therefore it really should not have more dependencies than base. In practice, one library with many dependencies will cause a long download time, long build time, and huge build results that is far more bloated than necessary. It also make the whole project more brittle: Build breaks, for whatever reason.
But convertible has 6 dependency packages. That's 13 if you include transitive dependencies: array, binary, bytestring, containers, deepseq, mtl, old-locale, old-time, pretty, template-haskell, text, time, and transformers. lawful-conversions has 11, which is 44 with transitive dependencies.
There are perfectly legitimate use cases of Haskell that require type conversion but do not need any of those dependencies, so I suggest we keep a library that provides the type conversion class without any dependencies (other than base) at all.