Magnus
Magnus

Reputation: 11396

Haskell type declarations

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

Answers (5)

hammar
hammar

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

leftaroundabout
leftaroundabout

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

Daniel
Daniel

Reputation: 1663

You might find explanations in this Learn You a Haskell chapter handy.

Upvotes: 1

amindfv
amindfv

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

jberryman
jberryman

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

Related Questions