Reputation: 114
I have a function (a->a)
which can take in different types but is there a way to determine what datatype the parameter is?
Like
foo :: a -> a
foo a == int =..
foo a == char =..
Is there anyway to do a check like this in haskell?
Upvotes: 0
Views: 2285
Reputation: 116139
A way to do this, which however I do not recommend, is to add a Typeable
constraint.
foo :: forall a . Typeable a => a -> a
foo x = case eqT :: a :~: Int of -- check if a = Int
Just Refl -> x + 1 -- here we can use x as an Int
Nothing -> x -- here we can not use x as an Int
For this to work you need a number of extensions, such as ScopedTypeVariables
and GADTs
.
This is usually not a good idea, in general. Before adopting this, you should first understand if you really need it: Typeable
is very powerful and it should be used as a last resort, when simpler alternatives are not enough. Perhaps a custom type class could be a better solution for your tasks, as AJFarmar showed.
Also note that, without a type class constraint, a function foo :: a -> a
, according to its "free theorem" (AKA parametricity property) can only be the identity function, or be undefined (e.g. infinite recursion, or a runtime exception).
Upvotes: 4
Reputation: 11913
No.
Use a datatype instead:
data MyType = MyInt Int | MyChar Char
foo :: MyType -> MyType
foo (MyInt i) = MyInt (i + 1) -- Or whatever
foo (MyChar c) = case c of {'a' -> MyChar 'A'; k -> MyChar k}
Though this of course restricts what types you can use.
Alternatively, use a typeclass:
class MyClass a where
foo :: a -> a
instance MyClass Int where
foo i = i + 1
instance MyClass Char where
foo c = case c of {'a' -> 'A'; k -> k}
-- N.B. foo :: MyClass a => a -> a
Though once again this restricts what types you can use.
Upvotes: 6