{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE PatternGuards #-} -- Pattern-matching on HList's Records {- See the thread `Re: (small) records proposal for Haskell '06' Haskell mailing list, January 2006 http://www.haskell.org/pipermail/haskell/2006-January/017276.html Joel Reymont wrote: > How does pattern matching work with HList? > I would like to pass a HList to a function and only match if a > certain field had a certain value. The code below defines the function foo that accepts a record and yields one value if the field PtX of the record has the value 0. If the field has any other value, a different result is returned. The function is written in a pattern-matching style. Also, the function is record-polymorphic: it takes _any_ record (of any `record type') that happens to have the field names PtX. *Test> :t foo foo :: (Num v, HasField (Proxy PtX) r v) => r -> [Char] -} module Main where import Data.HList makeLabels ["px","py"] -- Labels -- The more convenient labels, Label4.hs, need -fallow-overlapping-instances -- The less convenient label representation needs fewer extensions. -- We go for more convenient... {- data PtX; px = proxy::Proxy PtX data PtY; py = proxy::Proxy PtY -} accessor r f = r # f -- 1D points point1 x = px .=. x .*. emptyRecord -- 2D points point2 x y = px .=. x .*. py .=. (y + 10) .*. emptyRecord -- Record-polymorphic function, which illustrates record pattern-matching, -- with the help of generalized guards foo p | 0 <- p # px = "X is zero" foo _ = "something else" test1 = foo (point1 0) -- X is zero test1' = foo (point1 42) -- something else test2 = foo (point2 10 20) -- something else -- inline construction of the record test3 = foo (py .=. False .*. px .=. 0 .*. emptyRecord) -- X is zero main = do putStrLn test1 putStrLn test1' putStrLn test2 putStrLn test3