Difference between revisions of "Compatibility Modules"

From HaskellWiki
Jump to navigation Jump to search
(Created page with "= Motivation = It can be difficult to write code that maintains compatibility with multiple versions of dependencies. In many cases, a library author can decide to require us...")
 
Line 6: Line 6:
   
 
Instead, the core libraries committee has recommended an approach of releasing compatibility packages for each version of the base package. This document will lay out the design decisions we recommend, and why we decided on them.
 
Instead, the core libraries committee has recommended an approach of releasing compatibility packages for each version of the base package. This document will lay out the design decisions we recommend, and why we decided on them.
  +
  +
= Problem statement =
  +
  +
Consider a very simple (and obviously fake) example. Suppose base for some terrible reason decided to provide a function which attempts to parse an <code>Int</code> and, on failure, uses a default value of 0:
  +
  +
<pre>module Parse where
  +
  +
parseInt :: String -> Int
  +
parseInt s =
  +
case reads s of
  +
(i,""):_ -> i
  +
_ -> 0</pre>
  +
  +
This module makes it into base version 4.6 but then, when releasing base 4.7, we decide that the default value should really be an argument to the function instead of hard-coded to 0. Thus, our type signature changes to:
  +
  +
<pre>parseInt :: Int -> String -> Int</pre>
  +
  +
Making this change in base itself is trivial. The problem is for all the user code out there using <code>parseInt</code>. In order to allow user code to be compatible with both version 4.6 and 4.7 of base, the user must rely on techniques such as Cabal CPP macros, e.g.:
  +
  +
<pre>myFunc s = 5 +
  +
#if MIN_VERSION_base(4, 7, 0)
  +
parseInt 0 s
  +
#else
  +
parseInt s
  +
#endif</pre>
  +
  +
Such conditionals are tedious and error-prone. The goal of this proposal is to simplify the life of users trying to write code that will compile against multiple GHC versions, while allowing GHC-bundled libraries to be updated in reasonable manner.

Revision as of 18:36, 2 September 2013

Motivation

It can be difficult to write code that maintains compatibility with multiple versions of dependencies. In many cases, a library author can decide to require users to upgrade to a more recent version of dependencies. However, in the case of libraries bundled with GHC, this means upgrading the compiler, which in many cases is not an option.

One possible response would be to try and lock down the APIs for this libraries to avoid any migration headaches. However, such an approach would ultimately lead to quite convoluted APIs at the core of our ecosystem.

Instead, the core libraries committee has recommended an approach of releasing compatibility packages for each version of the base package. This document will lay out the design decisions we recommend, and why we decided on them.

Problem statement

Consider a very simple (and obviously fake) example. Suppose base for some terrible reason decided to provide a function which attempts to parse an Int and, on failure, uses a default value of 0:

module Parse where

parseInt :: String -> Int
parseInt s =
    case reads s of
        (i,""):_ -> i
        _ -> 0

This module makes it into base version 4.6 but then, when releasing base 4.7, we decide that the default value should really be an argument to the function instead of hard-coded to 0. Thus, our type signature changes to:

parseInt :: Int -> String -> Int

Making this change in base itself is trivial. The problem is for all the user code out there using parseInt. In order to allow user code to be compatible with both version 4.6 and 4.7 of base, the user must rely on techniques such as Cabal CPP macros, e.g.:

myFunc s = 5 +
#if MIN_VERSION_base(4, 7, 0)
    parseInt 0 s
#else
    parseInt s
#endif

Such conditionals are tedious and error-prone. The goal of this proposal is to simplify the life of users trying to write code that will compile against multiple GHC versions, while allowing GHC-bundled libraries to be updated in reasonable manner.