4
votes

for a homework assignment, a subtask is to make the arithmetic functions (+), (-), (*) and div showable.

We're solved the rest of the assignment, but we're stuck here. Right now we're using the solution to this question here to distinguish between the operations:

showOp op = case op 3 3 of
          6 -> "plus"
          0 -> "minus"
          9 -> "times"
          1 -> "divide"
          _ -> "undefined"

However, this strikes me as kind of ugly as things like showOp (\a b -> a * 3 - y) yield "plus".

Is there any way to better distinguish between the operators?

We are using winhugs atm with the appropriate switches -98 +o in order to be able to use the needed extensions.

Edit: As requested, the actual assignment has to do with Arrays (specifically Array Int (Int -> Int -> Int)). It has to do with generating arrays of operators that fulfill certain conditions.

The assignment states:

Make the data type Array Int (Int->Int-Int) an Instance of Show. The arithmetic operations from the previous exercises should be represented as "plus", "minus", "times" and "div".

thx for any help in advance

1
I would be nice to see some more context from the assignment, because making functions themselves showable seems like a strange requirement for homework. - shang
If the requirement is explicitly for Int->Int->Int, there is little better you can do than such a heuristic unsafe case table. (It would be possible to make it much nicer if general (Num a) => a->a->a was allowed...) - leftaroundabout
I think that is as good as you are going to see--I think it is absolutely impossible to check equality for functions, which means that you need to check for operational equivalence. You could expand the range of tests to catch more undefined functions, but not much more. - isturdy
@isturdy: You could check functions of type Int -> Int -> Int for extensional equality easily enough. You just need to apply both functions to all possible arguments and check that they produce the same result! It might take a while, though. - C. A. McCann
True, I forgot that Int is bounded. But I do get somewhat impatient... - isturdy

1 Answers

2
votes

Use induction :)

{-# LANGUAGE FlexibleInstances #-}

instance Eq (Int-> Int -> Int) where 
  f == g = induce f g where
    base = 1
    n = 2
    induce f g = and [f 1 n' == g 1 n' | n' <- [base, n, n+1]]

instance Show (Int-> Int -> Int) where 
  show a = showOp a where
    showOp op = case lookup op ops of
                  Just a -> a
                  otherwise  -> "undefined"
    ops = [((+),"plus")
          ,((-),"minus")
          ,((*),"times")
          ,(div,"divide")]

Output:

*Main> (\a b -> a * 3 - b) :: (Int->Int->Int)
undefined