Hải Bình
Hải Bình

Reputation: 91

How to make this Haskell function typecheck

data D = A Int Int | B Int Char

instance Show D where
    show (A a b) = show b
    show (B a b) = show b

hehe :: D -> String
hehe d = show u ++ show v
     where (u, v) = show <$> case d of 
            A a b -> (a + 1, b)
            B a b -> (a + 2, b) 

The idea is that I want to apply a function over a tuple, but it does not type check because the second element of the tuple can either be an Int or a Char.

Here is the error message:

    * Couldn't match expected type `Int' with actual type `Char'
    * In the expression: b
      In the expression: (a + 2, b)
      In a case alternative: B a b -> (a + 2, b)
   |
11 |             B a b -> (a + 2, b)
   |              

I wonder if there is an elegant solution to solve this?

Upvotes: 2

Views: 75

Answers (1)

Noughtmare
Noughtmare

Reputation: 10695

You can just push the show into the case:

hehe :: D -> String
hehe d = show u ++ show v
     where (u, v) = case d of 
            A a b -> (a + 1, show b)
            B a b -> (a + 2, show b) 

If you really, really want to delay the show then you can use the ExistentialQuantification language extension:

data SomeShow = forall a. Show a => SomeShow a

hehe :: D -> String
hehe d = show u ++ show v
     where (u, v) = (\(SomeShow x) -> show x) <$> case d of 
            A a b -> (a + 1, SomeShow b)
            B a b -> (a + 2, SomeShow b)

That is not worth it in this case.

Upvotes: 5

Related Questions