3

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?

5 Answers 5

13

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 
Sign up to request clarification or add additional context in comments.

1 Comment

I see, so the key difference then is that in my code, String is a type instead of a typeclass. Thanks for clarifying that distinction for me. I figured they could be used interchangeably.
3

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.

3 Comments

Can you explain what you mean by "more difficult for the compiler to resolve"? That doesn't sound right on the face of it.
@DanielWagner: well, honestly I don't know how difficult it is for the compiler. I just have a feeling there is more to it then simply a local type A = String synonym.
I will feel more comfortable voting for this answer if you remove the FUD.
3

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.

1 Comment

Another very helpful answer, thanks! The yield of instructive answers has been very high for me on this question.
1

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

Comments

1

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

2 Comments

Actually it was precisely that chapter that triggered my question. Based on that chapter's examples, which used Integral instead of String, I expected the above code to compile.
You can try this at the ghci prompt to get an idea of the difference between these things. ghci> :type Integral -- this should give an error. ghci> :info Integral -- this will give you the class definition for Integral. Now try that with String.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.