[Haskell-beginners] Help in pattern matching
Stephen Tetley
stephen.tetley at gmail.com
Mon Mar 8 09:14:09 EST 2010
Hi Joe - I've cc'ed back to list...
I'm supposing from what you've said that only DataConst1 & DataConst2
have ids - so I've made a type synonym VId
type VId = Int
data TestData = DataConst1 VId String
| DataConst2 VId Int
| DataConst3 Sting String
| DataConst4 String Int
If both DataConst1 & DataConst2 have VId's the you right - you have to
pattern match for both:
setVid_to_4 :: TestData -> TestData
setVid_to_4 (DataConst1 _ y) = DataConst1 4 y
setVid_to_4 (DataConst2 _ y) = DataConst2 4 y
setVid_to_4 var = var
If all the cases of TestData had a VId e.g.:
data TestData = DataConst1 VId String
| DataConst2 VId Int
| DataConst3 VId Sting String
| DataConst4 Vid String Int
... then you could factor out VId to get these two data types
data FactoredTD = FactoredTD VId TD
data TD = DC1 String
| DC2 Int
| DC3 String String
| DC4 String Int
setVid_to_4 :: FactoredTD -> FactoredTD
setVid_to_4 (FactoredTD _ y) = FactoredTD 4 y
This factoring transformation is quite common.
For your particular data type you could factor the other way:
data TestDataX = DataConst1_or_2 VId (Either String Int)
| DataConst3 Sting String
| DataConst4 String Int
setVid_to_4 :: TestDataX -> TestDataX
setVid_to_4 (DataConst1_or_2 _ y) = DataConst1_or_2 4 y
setVid_to_4 y = y
However this factoring is quite horrible - I can't think of anywhere
where I've seen it.
Generally I wouldn't be too concerned about redundancy in pattern
matching. If its easy to consistently name all the constructors in an
algebraic data type, then that's a strong indication that you've put
it into a good form.
If you're still taxed by duplicate pattern matching you can then write
projection and modification functions to do it once and once only:
-- Has to return a Maybe as DC3 and DC4 have no ID
getVId :: TestData -> Maybe VId
getVid (DataConst1 iden _) = Just iden
getVid (DataConst2 iden _) = Just iden
getVid _ = Nothing
-- note - uses an update function that accesses the original value
-- rather than a simple replace
--
updateVid :: (Vid -> Vid) -> TestData -> TestData
updateVid f (DataConst1 iden y) = DataConst1 (f iden) y
updateVid f (DataConst2 iden y) = DataConst2 (f iden) y
updateVid f var = var
incrementVid :: TestData -> TestData
incrementVid = updateVid (\x -> x+1)
Best wishes
Stephen
On 8 March 2010 12:19, Joe Fox <fox.joe87 at gmail.com> wrote:
> Hi Guys,
>
> First thanks for all yours inputs.
>
> Actually test is just a simple function , actually my actual function is
> pretty complex and huge ...
>
> let me redefine Test function , i guess i took a bad example which created
> lot of confusion
>
> the type of the test functions will be something like this , (i don't have
> any ambiguity on type of the function, )
>
> test:: TestData -> TestData
>
> My question is like is there any way i can match multiple pattern in a
> function statement .
>
> like this (I know this doesnt work , but just trying to explain whats on my
> mind)
>
>
> test var@(DataConst1 x y) == var@(DataConst2 x y) = var{id=4} -- let's say
> id is the record holder for first record
> test var@(_) = var --- any for other two its returns the same
>
> the working code would be like
> test var@(DataConst1 x y) = var{id=4}
> test var@(DataConst2 x y) = var{id=4} --- I want these two lines in one
> line, because the logic is same
> test var@(_) = var
>
> some thing of this sort.
> I hope i didnt add to the confusion
>
>
> Thanks
> Joe
>
More information about the Beginners
mailing list