Skip to content

Instantly share code, notes, and snippets.

@joom
Last active December 8, 2020 22:21
Show Gist options
  • Save joom/d55b4cd0fab8f0d8c63aa21457f4f64f to your computer and use it in GitHub Desktop.
Save joom/d55b4cd0fab8f0d8c63aa21457f4f64f to your computer and use it in GitHub Desktop.
Find out if a value matches a certain constructor.
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}
import Data.Data
import Unsafe.Coerce
type family Last (a :: *) :: * where
Last (b -> c) = Last c
Last d = d
full :: (Typeable a, Data (Last a)) => a -> Last a
full x = case typeRepArgs (typeOf x) of
[] -> error "Impossible"
xs -> apps (length xs - 1) x
where apps 0 t = unsafeCoerce t
apps n t = apps (n - 1) ((unsafeCoerce t) undefined)
valueIsConstructedBy :: (Typeable a, Data (Last a)) => a -> Last a -> Bool
valueIsConstructedBy x y = toConstr (full x) == toConstr y
main :: IO ()
main = do
print $ filter (valueIsConstructedBy Just) ([Just 4, Nothing, Just 5] :: [Maybe Int])
print $ filter (valueIsConstructedBy (:)) ([[1,2],[],[3,4],[],[5]] :: [[Int]])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment