Relatively little has been written on Elgot algebras in Haskell. While this example is a little simple-minded (computing Collatz sequences for numbers), it is to my knowledge the only example of Elgot algebras with code1. Moreover, it shows off several of Haskell's strengths.
The Collatz sequence of a given number can be computed in Haskell as follows:
collatz :: Int -> [Int]
collatz 1 = [1]
collatz n
| n mod
2 == 0 = n:(collatz (div n 2))
| otherwise = n:(collatz (3 * n + 1))
But we can do better! Let's see what our code looks like with an Elgot algebra:
import Data.Functor.Foldable
-- | Values provided by https://oeis.org/A006877
coalgebra :: Int -> Either [Int] (ListF Int Int)
coalgebra 1 = Left [1]
coalgebra 2 = Left [2, 1]
coalgebra 3 = Left [3, 10, 5, 16, 8, 4, 2, 1]
coalgebra n
| n mod
2 == 0 = Right $ Cons n (div n 2)
| otherwise = Right $ Cons n (3 * n + 1)
collatz :: Int -> [Int]
collatz = elgot embed coalgebra
It's a good deal more verbose. But it's also more efficient, at least for small values.
As it happens, we can extend the improved performance using Template Haskell, with the added benefit that we won't tangle ourselves up by trying to write things by hand. We will now need two modules now, but otherwise it's relatively straightforward.
module CollatzTH (collatzTH) where
collatzTH :: Int -> [Int]
collatzTH 1 = [1]
collatzTH n
| n mod
2 == 0 = n:(collatzTH (div n 2))
| otherwise = n:(collatzTH (3 * n + 1))
Our second module will import the first:
{-# LANGUAGE TemplateHaskell #-}
module Collatz (collatz) where
import CollatzTH
import Data.Functor.Foldable
import Language.Haskell.TH.Syntax
-- | Values provided by https://oeis.org/A006877
coalgebra :: Int -> Either [Int] (ListF Int Int)
coalgebra 1 = Left [1]
coalgebra 2 = Left $( lift (collatzTH 2) )
coalgebra 3 = Left $( lift (collatzTH 3) )
coalgebra 6 = Left $( lift (collatzTH 6) )
coalgebra 7 = Left $( lift (collatzTH 7) )
coalgebra 9 = Left $( lift (collatzTH 9) )
coalgebra 18 = Left $( lift (collatzTH 18) )
coalgebra n
| n mod
2 == 0 = Right $ Cons n (div n 2)
| otherwise = Right $ Cons n (3 * n + 1)
collatz :: Int -> [Int]
collatz = elgot embed coalgebra
Here, one of the advantages of Elgot algebras comes to the fore: we can effectively mix a "supercompiler" with normal recursion. While the Collatz sequence example does not generalize easily, it's not hard to imagine this being useful.
1: In fact, I seached for a use of an Elgot algebra in every package on Hackage, but found only the definitions in recursion-schemes