Reputation: 129
I want to pass a function a wildcard or any type or even a way to choose between either of multiple types rather than just restrict it to String, or Number, or Boolean, for example:
myFunction :: a -> String
or
myFunction :: _ -> String
or
myFunction :: (String || Number) -> String
Is that possible?
Upvotes: 3
Views: 1825
Reputation: 89053
myFunction :: a -> String
means that myFunction
can take an argument of any type, but will always return a string. This is legal Haskell syntax.
With PartialTypeSignatures
enabled, myFunction :: _ -> String
is legal Haskell syntax, with _
acting as a "hole", or a way to get the compiler to tell you what type it inferred at that position:
Temp.hs:4:15: warning: [-Wpartial-type-signatures]
• Found type wildcard ‘_’ standing for ‘String’
• In the type signature: myFunction :: _ -> String
|
4 | myFunction :: _ -> String
| ^
If you enable TypeOperators
, then you can define type (||) = Either
, which make myFuncion :: (String || Number) -> String
mean that myFuncion
is a function that takes an argument of type Either String Number
and returns a String
:
type Number = Integer
type (||) = Either
myFuncion = (String || Number) -> String
myFuncion (Left string) = string
myFuncion (Right number) = show number
Upvotes: 4
Reputation: 120711
myFunction :: a -> String
is technically possible, however it's profoundly useless – since this must be able to deal with an argument of any type, there's nothing you can actually do with the argument. (It's a bit like getting a can with a completely unspecified substance – you wouldn't eat it in case it's corrosive, you couldn't use it for cleaning purposes in case it's fat, paint or glue, you couldn't process it further... in case of an unrestricted Haskell type you couldn't even analyse it.)
If you narrow it down to types that support some kind of common operation, a polymorphic argument can make sense:
myFunction' :: Show a => a -> String
myFunction' x = "The value is " ++ show x
Your other approach, supporting only two very specific types, is also possible:
myFunction'' :: Either String Integer -> String
myFunction'' (Left s) = "Got a string: “" ++ s ++ "”"
myFunction'' (Right n) = "Got a number: " ++ show n
Note that these two approaches are quite different: Show a => a -> String
can be used as String -> String
or as Integer -> String
, or in fact any other type which supports the show
operation (including newly-defined types of your own), but you must decide at compile-time which type you want. At runtime, all arguments passed to this function must then have the same type.
Either String Integer -> String
can accept a mixture of String
- and Integer
values at runtime, but is always restricted to only these two types.
Upvotes: 13
Reputation: 370142
Defining a function a -> String
is easily possible, it just won't be able to do anything useful unless you also restrict a
to some typeclass (like Show
).
_ -> String
is not valid syntax. If it were, I imagine it would do the same as a -> String
, so you can just use that.
(String || Number) -> String
is also not valid syntax, but Either String Number -> String
is. You can also define your data type with constructors for the types you want to allow.
Upvotes: 4