Skip to content

Instantly share code, notes, and snippets.

@bradparker
Last active October 16, 2018 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradparker/84b6d7132c97f70f939c87dbfb06c321 to your computer and use it in GitHub Desktop.
Save bradparker/84b6d7132c97f70f939c87dbfb06c321 to your computer and use it in GitHub Desktop.
Constrained
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Constrained
( Constrained(unconstrained)
, constrain
) where
import Data.Bool ((&&), otherwise)
import Data.Eq (Eq)
import Data.Maybe (Maybe(Nothing, Just))
import Data.Ord (Ord, (<=))
import Data.Proxy (Proxy(Proxy))
import GHC.Integer (Integer)
import GHC.TypeLits (KnownNat, Nat, natVal)
import Text.Show (Show)
newtype Constrained a (min :: Nat) (max :: Nat)
= Constrained { unconstrained :: a }
deriving (Eq, Ord, Show)
-- E.G:
-- > import qualified Data.Text as Text
-- > import Data.Text (Text)
-- > :{
-- | validText :: Text -> Maybe (Constrained Text 8 100)
-- | validText = constrain (fromIntegral . Text.length)
-- | :}
-- > validText (Text.pack "At least 8 chars")
-- Just (Constrained {unconstrained = "At least 8 chars"})
-- > validText (Text.pack "Smol!")
-- Nothing
-- > validText (Text.pack "Too looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong!")
-- Nothing
-- > validText (Text.pack "Not too loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong!")
-- Just (Constrained {unconstrained = "Not too loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong!"})
constrain ::
forall a min max. (KnownNat min, KnownNat max)
=> (a -> Integer)
-> a
-> Maybe (Constrained a min max)
constrain getLength a
| l <= len && len <= h = Just (Constrained a)
| otherwise = Nothing
where
len = getLength a
l = natVal (Proxy :: Proxy min)
h = natVal (Proxy :: Proxy max)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment