1

I tried the following code:

data InputType = NumType Int Int | StrType String String
data OutputType = Either Int String
add' :: InputType -> InputType -> OutputType
add' (NumType a b) = a + b
add' (StrType a b) = a ++ b

But failed :(

gongqj
  • 762
  • 6
  • 14
  • If this is not just an exercise, note that your specific problem can be solved with the [`Monoid`](https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Monoid.html) class: for instance, you can try, in GHCi, `import Data.Monoid` followed by `"foo" <> "bar"` and `Sum 2 <> Sum 3`. – duplode Oct 16 '16 at 02:09

2 Answers2

4

Your declaration of OutputType does not specify that it can be either an Int or a String; rather, you have created a new pair that requires both an Int and a String. Your data constuctor Either just happens to have the same name as the type constructor Either.

I think you meant

type OutputType = Either Int String

in which case you can then define your function if you use the correct constructors

add' :: InputType -> OutputType
add' (NumType a b) = Left (a + b)
add' (StrType a b) = Right (a ++ b)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • `• Couldn't match expected type ‘InputType -> OutputType’ with actual type ‘Either Int b0’ • Possible cause: ‘Left’ is applied to too many arguments In the expression: Left (a + b) In an equation for ‘add'’: add' (NumType a b) = Left (a + b)` – gongqj Oct 16 '16 at 01:34
  • 2
    @gongqj The problem is the signature you gave `add'`. For the function you wrote it should be `add' :: InputType -> OutputType` – duplode Oct 16 '16 at 01:44
  • Oh, I forgot to change the signature before. Thanks for you reply. Now, the definition is ok, but still failed when to call `add' $ NumType 1 2` _**Data constructor not in scope: NumInput :: Integer -> Integer -> InputType**_ – gongqj Oct 16 '16 at 12:56
  • It looks like you typed `NumInput` instead of `NumType`. – chepner Oct 16 '16 at 13:02
  • Sorry, I was just refactoring the type name, and then see your reply, so there is a typo. – gongqj Oct 16 '16 at 17:35
1

You could use a GADT to represent at the value level the type of the input you're getting:

{-# LANGUAGE GADTs #-}

module Add where

data SType a where
  SString :: SType String
  SInt    :: SType Int

add :: SType a -> a -> a -> a
add SString = (++)
add SInt    = (+)

I called the GADT SType because it's a singleton type.

Community
  • 1
  • 1
gallais
  • 11,823
  • 2
  • 30
  • 63