overloaded-0.1.2: Overloaded pragmas as a plugin

Safe HaskellNone
LanguageHaskell2010

Overloaded

Contents

Description

Overloaded* language extensions as a source plugin.

Synopsis

Plugin

plugin :: Plugin Source #

Overloaded plugin.

To enable plugin put the following at top of the module:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:Symbols #-}

At least one option is required, multiple can given either using multiple -fplugin-opt options, or by separating options with colon:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:Symbols:Numerals #-}

Options also take optional desugaring names, for example

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:Labels=Data.Generics.ProductFields.field #-}

to desugar OverloadedLabels directly into field from generics-lens (no need to import orphan instance!)

Supported options

  • Symbols desugars literal strings to fromSymbol @sym
  • Strings works like built-in OverloadedStrings (but you can use different method than fromString)
  • Numerals desugars literal numbers to fromNumeral @nat
  • Naturals desugars literal numbers to fromNatural nat (i.e. like fromString)
  • Chars desugars literal characters to fromChars c. Note: there isn't type-level alternative: we cannot promote Chars.
  • Lists is not like built-in OverloadedLists, but desugars explicit lists to cons and nil
  • If desugars if-expressions to ifte b t e
  • Labels works like built-in OverloadedLabels (you should enable OverloadedLabels so parser recognises the syntax)
  • TypeNats and TypeSymbols desugar type-level literals into FromNat and FromTypeSymbol respectively.

Known limitations

  • Doesn't desugar inside patterns

RecordFields

WARNING the type-checker plugin is experimental, it's adviced to use

{-# OPTIONS_GHC -ddump-simpl #-}

to avoid surprising segfaults.

Usage

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:RecordFields #-}

Implementation bits

See Note [HasField instances] in ClsInst, the behavior of this plugin is similar.

The HasField class is defined in GHC.Records.Compat module of record-hasfield package:

class HasField {k} x r a | x r -> a where
    hasField :: r -> (a -> r, a)

Suppose we have

data R y = MkR { foo :: [y] }

and foo in scope. We will solve constraints like

HasField "foo" (R Int) a

by emitting a new wanted constraint

[Int] ~# a

and building a HasField dictionary out of selector foo appropriately cast.

Idiom brackets from TemplateHaskellQuotes

{-# LANGUAGE TemplateHaskellQuotes #-}
{-# OPTIONS_GHC -fplugin=Overloaded -fplugin-opt=Overloaded:IdiomBrackets #-}

data Tree a
    = Leaf a
    | Branch (Tree a) (Tree a)
  deriving (Show)

instance Functor Tree where
    fmap f (Leaf x)     = Leaf (f x)
    fmap f (Branch l r) = Branch (fmap f l) (fmap f r)

instance Traversable Tree where
    traverse f (Leaf x)     = [| Leaf (f x) |]
    traverse f (Branch l r) = [| Branch (traverse f l) (traverse f r) |]

Overloaded:Symbols

class FromSymbol (s :: Symbol) a where Source #

Another way to desugar overloaded string literals using this class.

A string literal "example" is desugared to

fromSymbol @"example"

Enabled with:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:Symbols #-}

Methods

fromSymbol :: a Source #

Instances
(KnownNat y, KnownNat m, KnownNat d, ParseDay s ~ (,,) y m d) => FromSymbol s Day Source # 
Instance details

Defined in Overloaded.Symbols

(KnownSymbol s, SeqList (ToList s)) => FromSymbol s ByteString Source # 
Instance details

Defined in Overloaded.Symbols

(KnownSymbol s, SeqList (ToList s)) => FromSymbol s ByteString Source # 
Instance details

Defined in Overloaded.Symbols

KnownSymbol s => FromSymbol s Text Source # 
Instance details

Defined in Overloaded.Symbols

KnownSymbol s => FromSymbol s Text Source # 
Instance details

Defined in Overloaded.Symbols

(KnownSymbol s, a ~ Char) => FromSymbol s [a] Source # 
Instance details

Defined in Overloaded.Symbols

Methods

fromSymbol :: [a] Source #

Overloaded:Strings

Overloaded:Numerals

class FromNumeral (n :: Nat) a where Source #

Another way to desugar numerals.

A numeric literal 123 is desugared to

fromNumeral @123

Enabled with:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:Numerals #-}

One can do type-level computations with this.

Methods

fromNumeral :: a Source #

Instances
KnownNat n => FromNumeral n Nat Source # 
Instance details

Defined in Overloaded.Numerals

(KnownNat n, OverflowCheck n "Word8" (n <=? 18446744073709551615)) => FromNumeral n Word64 Source # 
Instance details

Defined in Overloaded.Numerals

(KnownNat n, OverflowCheck n "Word8" (n <=? 4294967295)) => FromNumeral n Word32 Source # 
Instance details

Defined in Overloaded.Numerals

(KnownNat n, OverflowCheck n "Word8" (n <=? 65535)) => FromNumeral n Word16 Source # 
Instance details

Defined in Overloaded.Numerals

(KnownNat n, OverflowCheck n "Word8" (n <=? 255)) => FromNumeral n Word8 Source # 
Instance details

Defined in Overloaded.Numerals

KnownNat n => FromNumeral n Int Source #

TODO: currently there is no range check

Instance details

Defined in Overloaded.Numerals

KnownNat n => FromNumeral n Integer Source # 
Instance details

Defined in Overloaded.Numerals

KnownNat n => FromNumeral n Natural Source # 
Instance details

Defined in Overloaded.Numerals

(FinFromNumeral (FromGHC n) m, IsLess (FromGHC n) m n (ToGHC m)) => FromNumeral n (Fin m) Source # 
Instance details

Defined in Overloaded.Numerals

Methods

fromNumeral :: Fin m Source #

defaultFromNumeral :: forall n a. (KnownNat n, Integral a) => a Source #

Default implementation of fromNumeral.

Usage example:

instance (KnownNat n, ...) => FromNumeral n MyType where
    fromNumeral = defaultFromNumeral @n

Overloaded:Naturals

class FromNatural a where Source #

Class for Natural-like datastructures

A numeric literal 42 is desugared to

fromNatural 42

Methods

fromNatural :: Natural -> a Source #

Instances
FromNatural Integer Source # 
Instance details

Defined in Overloaded.Naturals

FromNatural Natural Source # 
Instance details

Defined in Overloaded.Naturals

Overloaded:Chars

class FromChar a where Source #

Class for Char-like datastructures

A character literal x is desugared to

fromChar 'x'

Methods

fromChar :: Char -> a Source #

Instances
FromChar Char Source # 
Instance details

Defined in Overloaded.Chars

Methods

fromChar :: Char -> Char Source #

Overloaded:Lists

class Nil a where Source #

Class for nil, []

See test-suite for ways to define instances for Map. There are at-least two-ways.

Methods

nil :: a Source #

Instances
Nil [a] Source # 
Instance details

Defined in Overloaded.Lists

Methods

nil :: [a] Source #

n ~ Z => Nil (Vec n a) Source # 
Instance details

Defined in Overloaded.Lists

Methods

nil :: Vec n a Source #

xs ~ ([] :: [Type]) => Nil (NP f xs) Source # 
Instance details

Defined in Overloaded.Lists

Methods

nil :: NP f xs Source #

xs ~ ([] :: [[Type]]) => Nil (POP f xs) Source # 
Instance details

Defined in Overloaded.Lists

Methods

nil :: POP f xs Source #

class Cons x ys zs | zs -> x ys where Source #

Class for Cons :.

Methods

cons :: x -> ys -> zs Source #

Instances
Cons a [a] (NonEmpty a) Source # 
Instance details

Defined in Overloaded.Lists

Methods

cons :: a -> [a] -> NonEmpty a Source #

Cons a [a] [a] Source # 
Instance details

Defined in Overloaded.Lists

Methods

cons :: a -> [a] -> [a] Source #

Cons a (Vec n a) (Vec (S n) a) Source # 
Instance details

Defined in Overloaded.Lists

Methods

cons :: a -> Vec n a -> Vec (S n) a Source #

Cons (f x) (NP f xs) (NP f (x ': xs)) Source # 
Instance details

Defined in Overloaded.Lists

Methods

cons :: f x -> NP f xs -> NP f (x ': xs) Source #

Cons (NP f xs) (POP f xss) (POP f (xs ': xss)) Source # 
Instance details

Defined in Overloaded.Lists

Methods

cons :: NP f xs -> POP f xss -> POP f (xs ': xss) Source #

Overloaded:If

class ToBool b where Source #

Class for Bool-like datastrucutres

An if--expression if b then t else e is desugared to

ifte (toBool b) t e

Enabled with:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:If #-}

Methods

toBool :: b -> Bool Source #

Instances
ToBool Bool Source # 
Instance details

Defined in Overloaded.If

Methods

toBool :: Bool -> Bool Source #

ToBool (Maybe a) Source #

Just is True

Instance details

Defined in Overloaded.If

Methods

toBool :: Maybe a -> Bool Source #

ToBool (Either b a) Source #

Right is True

Instance details

Defined in Overloaded.If

Methods

toBool :: Either b a -> Bool Source #

ifte :: ToBool b => b -> a -> a -> a Source #

ToBool overloaded if-expression.

Overloaded:Labels

Overloaded:TypeNats

class FromNatC a Source #

A way to overload type level Nats.

A number type-literal 42 is desugared to

FromNat 42

Enabled with:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:TypeNats #-}

Associated Types

type FromNat (n :: Nat) :: a Source #

Instances
FromNatC Nat Source # 
Instance details

Defined in Overloaded.TypeNats

Associated Types

type FromNat n :: a Source #

FromNatC Nat Source # 
Instance details

Defined in Overloaded.TypeNats

Associated Types

type FromNat n :: a Source #

Overloaded:TypeSymbols

class FromTypeSymbolC a Source #

A way to overload type level Symbols.

A symbol type-literal "example" is desugared to

FromTypeSymbol "example"

Enabled with:

{-# OPTIONS -fplugin=Overloaded -fplugin-opt=Overloaded:TypeSymbols #-}

Associated Types

type FromTypeSymbol (s :: Symbol) :: a Source #

Instances
FromTypeSymbolC Symbol Source # 
Instance details

Defined in Overloaded.TypeSymbols

Associated Types

type FromTypeSymbol s :: a Source #

Overloaded:RecordFields

See GHC.Records.Compat from record-hasfield package.