validated-literals-0.2.0.1: Compile-time checking for partial smart-constructors

Copyright(C) 2015 Merijn Verstraaten
LicenseBSD-style (see the file LICENSE)
MaintainerMerijn Verstraaten <merijn@inconsistent.nl>
Stabilityexperimental
Portabilityportable
Safe HaskellNone
LanguageHaskell2010

ValidLiterals

Description

To disallow invalid input it is common to define (new)types with hidden data constructors. Forcing the user to go through a smart-constructor that enforces invariants and returns Maybe ResultType, preventing the construction of data with invalid values.

However, it is also common to want to include literal values of such types in source text. Things of textual literals for HTML, HTTP, etc. In such cases smart-constructors force us to handle potential conversion failures at runtime, or abusing functions like fromJust to break away all the safety smart-constructors provide. All this despite the fact that we can statically know at compile time that the conversion will always succeed or always fails.

This package provides a typeclasses for using TH to validate the correctness of provided literals at compile. This lets you define, e.g., newtype Even = Even Integer and write:

x :: Even
x = $$(valid 38)

This will check, at compile time, that the provided Integer is, in fact, even and unwrap it from Maybe, avoiding the runtime check.

Synopsis

Documentation

class Validate a b where Source #

Class for validated, compile-time, partial conversions from type a to b.

Minimal complete definition

fromLiteral

Methods

fromLiteral :: a -> Maybe b Source #

Converts a values into validated b values

valid :: Validate a b => a -> Q (TExp b) Source #

The core function of ValidLiterals, use this together with Typed Template Haskell splices to insert validated literals into your code. For example, if we assume newtype ASCII = ASCII Char where ASCII should only contain ASCII characters, we would write:

{-# LANGUAGE TemplateHaskell #-}

import ValidLiterals

x :: ASCII
x = $$(valid 'c')

validInteger :: Validate Integer b => Integer -> Q (TExp b) Source #

Integer literals lead to obnoxious defaulting complaints by GHC, by using this function you can force the defaulting to Integer, silencing these warnings.

Since Integral literals use fromInteger :: Num a => Integer -> a this function cannot cost you any precision.

validRational :: Validate Rational b => Rational -> Q (TExp b) Source #

Same as validInteger, but for Fractional values.

Since Fractional literals use fromRational :: Fractional a => Rational -> a this function cannot cost you any precision.

validString :: Validate String b => String -> Q (TExp b) Source #

Same as validInteger, but for when enabling OverloadedStrings makes String literals polymorphic.

validList :: Validate [a] b => [a] -> Q (TExp b) Source #

Same as validInteger, but for when enabling OverloadedLists makes list literals polymorphic.