Home > Software engineering >  compairing inputs in haskell
compairing inputs in haskell

Time:11-06

I do want to get a Tuple (String, Int) and another value a as my input in the following function:

getOtherPairValue :: Eq a => (String, Int) -> a -> Either a (b, a)

I want to compare the input a with my tuple and if the first element in my tuple doesn't match with the input a, I want to check if it matches with the second. If it doesn't match at all, I do want to return the Tuple as it is.

If the input a matches with either the string or the integer, I want to return the non matched element of my Tuple.

I tried it with the following function:

getOtherPairValue (s, i) e
  | e == i = Left s
  | e == s = Left i
  | e /= s && e /= i = Right (s, i)

CodePudding user response:

Before starting, let me tell you that this looks like a horrible idea to me. You are asking for a function taking a parameter that must be a string or a integer, then to return "the other type", and that copes with working in a typed language.

We do have something in Haskell that can achieve something similar to that, but I wonder if you really need to do that in the first place.

Anyway:

Use Either

getOtherPairValue :: (String, Int) -> Either String Int 
                  -> Either String (Either Int (String, Int))
getOtherPairValue (s, i) (Left  e) | e == s = Right (Left i)
getOtherPairValue (s, i) (Right e) | e == i = Left s
getOtherPairValue p      _                  = Right (Right p)

Note the nested Either returned by the function. That's needed since we must return a string, an integer, or a pair. Maybe it would be wise to return a custom sum type instead.

Tinker with type-level machinery

This is an overkill solution.

We first define "what's the other type in the tuple"

type family Other a where
   Other String = Int
   Other Int    = String

Then, we use Typeable to check at runtime whether the types are the same:

getOtherPairValue :: forall a. Typeable a 
                  => (String, Int) -> a -> Either (Other a) (String, Int)
getOtherPairValue p@(s, i) x = case (eqT @a @String, eqT @a @Int) of
   (Just Refl, _) | x == s -> Left i
   (_, Just Refl) | x == i -> Left s
   _                       -> Right p

This involves type families, GADTs, and Typeable. To me it looks tremendously complex for this operation, and this complexity is caused by having to implement a function which does not play well with types.

  • Related