relude-0.2.0: src/Relude/Extra/Newtype.hs
{-# LANGUAGE ScopedTypeVariables #-}
{- |
Copyright: (c) 2018 Kowainik
License: MIT
Maintainer: Kowainik <xrom.xkov@gmail.com>
Functions to ease work with newtypes.
-}
module Relude.Extra.Newtype
( un
, wrap
, under
) where
import Relude
-- $setup
-- >>> :set -XTypeApplications
{- | Unwraps value from @newtype@.
>>> newtype Size = Size Int deriving Show
>>> un @Int (Size 5)
5
>>> un (Size 5) == length ['a', 'x', 'b']
False
-}
un :: forall b a . Coercible a b => a -> b
un = coerce
{- | Wraps value to @newtype@. Behaves exactly as 'un' but has more meaningnful
name in case you need to convert some value to @newtype@.
>>> newtype Flag = Flag Bool deriving (Show, Eq)
>>> wrap False == Flag True
False
-}
wrap :: forall b a . Coercible a b => a -> b
wrap = coerce
{- | Applies function to the content of @newtype@. This function is not supposed
to be used on @newtype@s that are created with the help of smart constructors.
>>> newtype Foo = Foo Bool deriving Show
>>> under not (Foo True)
Foo False
>>> newtype Bar = Bar String deriving Show
>>> under (filter (== 'a')) (Bar "abacaba")
Bar "aaaa"
-}
under :: forall b a . Coercible a b => (b -> b) -> a -> a
under = coerce