0

If I have a constructor which is:

data Garage = Gar String 

if I want to test whether a type is equal to my garage type I would do something like this:

(==(Gar _)) (Gar "g") 

However, the compiler complains about the underscore. If I replace this with "g" it returns True. Is there a way so that I can compare with a wildcard?

0

4 Answers 4

4

Why doesn't your code work?

It looks like you want to pattern match, but actually you're calling the function == with arguments Gar _ and Gar "g". So Haskell gets confused and says something like "Pattern syntax in expression context: _".

How can it be fixed?

You can:

  1. add deriving Eq to the end of the data declaration, or

  2. implement Eq yourself:

    instance Eq Garage where (Gar l) == (Gar r) = l == r 

Is it possible to pattern match against constructor wildcards? (for completeness)

Yes, here's a nonsense function:

f :: Garage -> Int f (Gar "abc") = 12 f (Gar _) = 4 

This would probably be more useful with a datatype that had multiple constructors, though.

Sign up to request clarification or add additional context in comments.

1 Comment

Mog, if it's a _, it won't be used.
2

you want to do pattern match, like this:

case x of Gar _ -> True _ -> False 

if you want it as function, then add somsthing like

isGarage (Gar _) = True isGarage _ = False 

6 Comments

Yeh but I desire to return this from a function call
you can do that, it's expression and it's result can be passed/returned as any other value
that only returns a boolean, i desire to return the function which does the equality- not the result of the equality
why not to pass "isGarage" to your code? it's function after all, and can be passed as argument to another function or expression
If you want ta predicate function like this in general you can use DataConstructor {} no matter how many params the constructor has :)
|
0

Maybe your question assumes that you'll need to do run-time type checking in Haskell, but that's not necessary. Haskell will ensure all your types are correct at compile time, so a function which checks whether data is part of your Garage data type is not needed and wouldn't work:

justPrintGarages (Gar x) = print x -- if the argument is a Garage, print its content justPrintGarages _ = return () -- if it's anything else, do nothing. 

If we ask ghci what type justPrintGarages has, it will tell us

printGarages :: Garage -> IO () 

Yikes! Our function that was supposed to tell us whether we had a garage only works on garages??? Yup. That's because Haskell deliberately stops you from mixing types up, because it's a quagmire of runtime errors. Static typing is your friend. Static typing takes away a world of pain. Because of static typing, you can't define

printGaragesAndShebangs (Gar x) = print x printGaragesAndShebangs ('#':'!':xs) = putStr xs printGaragesAndShebangs _ = return () 

You'll get a type error. You can't just treat Strings and Garages the same.

If you want to mix garages and strings, here's the way to do it, keeping type safety:

data GarageStringInt = GsiG Garage | GsiS String | GsiI Int 

(GarageStringInt is a horrible name and so are GisG etc, but if you need this in your code it'll represent something sensible (I hope) and you can give it a name that describes what it represents.)

Now we can write

printGaragesAndShebangs :: GarageStringInt -> IO () printGaragesAndShebangs (GsiG (Gar x)) = print x printGaragesAndShebangs (GsiS ('#':'!':xs)) = putStr xs printGaragesAndShebangs _ = return () 

Comments

0

A function like

isGarage (Gar _) = True isGarage _ = False 

is pretty useless as it has type Garage -> Bool. So it will always return True for Garage type and type check failure will occur for any other type.

I think patter matching would be sufficient for your requirement. But just to show that you can have such kind of function using type classes if you know the types you will be acting on. So possibly if you know you will be getting values from a given set of types then you can do something like

{-# LANGUAGE FlexibleInstances #-} data Garage = Gar String class IsGarage a where isGarage :: a -> Bool isGarage _ = False instance IsGarage Garage where isGarage _ = True instance IsGarage [Char] 

In ghci

*Main> :t isGarage isGarage :: IsGarage a => a -> Bool *Main> isGarage "3" False *Main> isGarage (Gar "2") True 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.