variant-1.0.2: Variant and EADT
Safe HaskellNone
LanguageHaskell2010

Data.Variant.Syntax

Description

Rebindable syntax for Variant

This module provides RebindableSyntax-based do-notation for V. We recommend using VEither or Data.Variant.Excepts instead, which provide proper Monad instances without requiring RebindableSyntax.

Do-notation with Variants

We can use do-notation with V as we would with other sum types such as Maybe or Either. However, as we cannot have a Monad instance for V, we rely on the RebindableSyntax extension to mimic it.

The leftmost type is extracted from the Variant with >>= (or x <- myVariant with do-notation syntax). Variant types are concatenated on the left.

Function foo in the following example composes functions returning Variants by using do-notation:

{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RebindableSyntax #-}

import Data.Variant
import Data.Variant.Syntax

import Prelude hiding (head,lookup,(>>=),(>>),return)
import qualified Prelude
import Text.Read

foo :: String -> V [Integer, ParseError, LookupError Char, HeadError]
foo str = do
   c <- head str
   r <- lookup c codeMap
   parse (r ++ tail str)

   where
      codeMap :: [(Char, String)]
      codeMap = [ ('x', "0x")
                , ('d', "")
                ]


data ParseError = ParseError deriving Show

parse :: String -> V [Integer,ParseError]
parse s = case readMaybe s of
   Just i  -> V @Integer i
   Nothing -> V ParseError

data HeadError = ListWasEmpty deriving Show

head :: [a] -> V [a,HeadError]
head []    = toVariantAt @1 ListWasEmpty
head (x:_) = toVariantAt @0 x

data LookupError k = KeyWasNotPresent k deriving Show

lookup :: Eq k => k -> [(k,v)] -> V [v,LookupError k]
lookup k vs = case Prelude.lookup k vs of
   Just v  -> toVariantAt @0 v
   Nothing -> toVariantAt @1 (KeyWasNotPresent k)

Test:

> foo "d10"
V @Integer 10

> foo "x10"
V @Integer 16

> foo "u10"
V @(LookupError Char) (KeyWasNotPresent 'u')

> foo ""
V @HeadError ListWasEmpty

> foo "d10X"
V @ParseError ParseError

Documentation

(>>=) :: forall x (xs :: [Type]) (ys :: [Type]). KnownNat (Length ys) => V (x ': xs) -> (x -> V ys) -> V (Concat ys xs) Source #

(>>) :: forall (xs :: [Type]) (ys :: [Type]). V xs -> V ys -> V (Concat ys xs) Source #

return :: x -> V '[x] Source #