Can I capture values from a pattern synonym?

141 views Asked by At

Assuming a pattern:

pattern P :: [Int]
pattern P <- a:_

Can I somehow use a in the function f?

f :: [Int] -> Int
f P = a

The code above generates an error of Not in scope: 'a'.

2

There are 2 answers

3
Bartek Banachewicz On BEST ANSWER

Ok, this is slightly embarrasing, but I found that just doing this works:

{-# LANGUAGE PatternSynonyms #-}

pattern P :: Int -> [Int]
pattern P a <- a:_

f :: [Int] -> Int
f (P b) = b

main = print $ f [42]

The key point here is that the pattern parameter becomes explicit, but then it's also passed as an b pattern1 which will be matched. I was missing this one piece of the puzzle.

The drawback is that obviously you need to enumerate all parts of the pattern you want to use.


1Of course this can still be called a, I just named it differently for illustration.

0
rampion On

Do you want something like this?

{-# LANGUAGE PatternSynonyms, RecordWildCards #-}
module Temp where

pattern Cons :: a -> [a] -> [a]
pattern Cons { car, cdr } <- car:cdr

safeHead :: [a] -> Maybe a
safeHead Cons{..} = Just car
safeHead _ = Nothing

This used to cause errors but should work with recent releases of GHC.

Bear in mind that car and cdr are defined globally as functions and shadowed locally via RecordWildCards:

ghci> :browse Temp
pattern Cons :: a -> [a] -> [a]
car :: [a] -> a
cdr :: [a] -> [a]
safeHead :: [a] -> Maybe a