{-# 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