{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} import GHC.TypeLits import Data.Proxy (Proxy(..)) pattern Append :: forall (p :: Symbol). KnownSymbol p => String -> String pattern Append full <- (takePrefix (symbolVal (Proxy @p)) -> Just full) where Append full = symbolVal (Proxy @p) ++ full takePrefix :: String -> String -> Maybe String takePrefix prefix full | let (pre, post) = splitAt (length prefix) full , pre == prefix = Just post | otherwise = Nothing foo :: String -> IO () foo (Append @"this" s) = putStrLn $ "this and then: " ++ s foo s = putStrLn $ "something else: " ++ s main :: IO () main = do foo "this is a string" foo "those aren't"