0

I wish to define addition between two chars as concatination but im unsure of how to properly do so.

my attempt:

instance Num Char where
 (+) (a) (b) = [a] ++ [b]

but the error i get is that the return type is not the expected one.

My expected output is as stated a list of Char which is formed by concatinating the two chars.

3
  • 1
    (+) :: Num a => a -> a -> a; you want something with type Char -> Char -> [Char]. Commented Mar 11, 2019 at 20:04
  • Even if you did come up with a definition of + that fit the signature, you can't define a Num instance without also defining (*), abs, signum, fromInteger, and either negate or (-). And if you do define them, they still need to obey various laws like a + b == b + a and x + fromInteger 0 == x. The kind of operator overloading provided by type classes is not the free-for-all, any-definition-goes kind provided by other languages. Commented Mar 11, 2019 at 20:50
  • @chepner The built-in Natural type doesn't have a reasonable definition of negate or (-), and it breaks a lot of the "laws" (which aren't actually defined in the report). Commented Mar 11, 2019 at 23:47

2 Answers 2

7

Rather than overload (+) with non-numeric semantics, define your own character "addition" operator.

import Data.Function

-- The ^ is meant to suggest lifting values into a list.
(^+) :: a -> a -> [a]
x ^+ y = (++) `on` pure
-- Or more simply,
-- x ^+ y = [x, y]

Then 'a' ^+ 'b' == "ab". (^+) will work for creating a two-element list of any type, not just Char.

> 'a' ^+ 'b'
"ab"
> 3 ^+ 4
[3,4]
> [1,2] ^+ [4,5]
[[1,2],[4,5]]
Sign up to request clarification or add additional context in comments.

4 Comments

Bringing out the big cannons, eh? on, pure... you just barely missed generalizing (++) to (<>) to make it as inscrutable as possible. We have lost touch with how simple Haskell can be, it seems. a ^+ b = [a, b] (Upvoted anyway.)
Sorry, I performed what I thought was an edit suggestion but ended up actually editing the answer; my SO is a bit rusty. I agree with the main idea of the answer, but proposed a more reasonable implementation of ^+. Feel free to edit back if you feel like the original implementation is more reasonable.
@JustinL. You have enough reputation that your edits don't need peer review: you're expected to know well enough how things work and not make wantonly unreasonable edits. Case in point: this edit was totally reasonable.
I'd prefer an addition to the answer rather than omitting the on solution altogether.
5

This is impossible. The (+) function in Num has type a -> a -> a, so the return type must be the same as the parameter type. You cannot add two Char and receive a String as a result. More generally, you should not implement Num for things other than arithmetic on numbers.

4 Comments

I see, but if i took two strings as input and concatinated them, in other words a typesignature [Char] -> [Char] -> [Char], it would then be possible to define (+) on [Char] ?
The compiler would not complain, but any humans reading your program would.
The docs for Num specify a few laws that instances should satisfy, and concatenating strings wouldn't fit them. For example, string concatenation wouldn't satisfy addition commutativity. The compiler will not object, but such instance will have weird behavior, unobvious to other people, and thus will lead to subtle bugs.
Also, it occurs to me now, the compiler would complain. You must define an instance for [a] in general, and cannot specialize to only [Char]. You could define addition for lists to be concatenation, but of course this would be widely reviled.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.