Reputation: 11396
In Haskell, why does this compile:
splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")
but this does not:
splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")
>> Type constructor `String' used as a class
I would have thought these were the same thing. Is there a way to use the second style, which avoids repeating the type name 3 times?
Upvotes: 3
Views: 489
Reputation: 139830
Is there a way to use the second style, which avoids repeating the type name 3 times?
For simplifying type signatures, you may use type synonyms. For example you could write
type S = String
splice :: S -> S -> S
or something like
type BinOp a = a -> a -> a
splice :: BinOp String
however, for something as simple as String -> String -> String
, I recommend just typing it out. Type synonyms should be used to make type signatures more readable, not less.
In this particular case, you could also generalize your type signature to
splice :: [a] -> [a] -> [a]
since it doesn't depend on the elements being characters at all.
Upvotes: 3
Reputation: 120711
Actually, it is possible:
Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String
This uses the equational constraint ~
. But I'd avoid that, it's not really much shorter than simply writing String -> String -> String
, rather harder to understand, and more difficult for the compiler to resolve.
Upvotes: 3
Reputation: 1663
You might find explanations in this Learn You a Haskell chapter handy.
Upvotes: 1
Reputation: 8458
The =>
syntax in types is for typeclasses.
When you say f :: (Something a) => a
, you aren't saying that a
is a Something
, you're saying that it is a type "in the group of" Something
types.
For example, Num
is a typeclass, which includes such types as Int
and Float
.
Still, there is no type Num
, so I can't say
f :: Num -> Num
f x = x + 5
However, I could either say
f :: Int -> Int
f x = x + 5
or
f :: (Num a) => a -> a
f x = x + 5
Upvotes: 13
Reputation: 16635
Well... String
is a type, and you were trying to use it as a class.
If you want an example of a polymorphic version of your splice
function, try:
import Data.Monoid
splice :: Monoid a=> a -> a -> a
splice = mappend
EDIT: so the syntax here is that Uppercase words appearing left of =>
are type classes constraining variables that appear to the right of =>
. All the Uppercase words to the right are names of types
Upvotes: 1