Joe
Joe

Reputation: 183

Haskell: How to stop program printing Left or Right

I've made a calculator in haskell which I run from within GHCi. However since the final number can be an integer or double I've made the type declaration

calc :: String -> Either Integer Double

However the output of the function always has either left or right in front of it for example

Left 7

Right 8.4

Is there a way I can stop the left and right being printed?

Upvotes: 4

Views: 1259

Answers (2)

leftaroundabout
leftaroundabout

Reputation: 120731

The fancy way

(Probably, the other, less fancy solution below is better for you)

If you're only concerned about ghci, there's now (GHC>=7.6) the possibility to use a custom print function. You'd just specify, say,

type CalcResult = Either Integer Double

calcPrint :: CalcResult -> IO()
calcPrint (Left intg) = print intg
calcPrint (Right floatng) = print floatng

and then load ghci by

$ ghci YourModule.hs -interactive-print=YourModule.calcPrint SpecPrinter

This way, it's going to be a bit annoying: calcPrint can only use CalcResult, so you wouldn't be able to display anything else. To get around this, you can use a type class,

{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}

data CalcResult            -- We must prevent the 'Show' instance of 'Either' from
   = IntegerResult Integer -- getting in our way. (This type is better anyway,
   | FloatingResult Double -- you might want to add more types (e.g. 'Complex')
                           -- later, which is no good with 'Either'.)

class CalcShow c where
  calcShow :: c -> String

instance (Show c) => CalcShow c where
  calcShow = show

instance CalcShow CalcResult where
  calcShow (IntegerResult intg) = show intg
  calcShow (FloatingResult floatng) = show floatng

calcPrint :: CalcShow c => c -> IO()
calcPrint = putStrLn . calcShow

This way you will be able to display calculation results the way you'd like, as well as anything in the old Show class:

$ ghci-7.6 GHCI_Customprint.hs -interactive-print=GHCI_Customprint.calcPrint
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling GHCI_Customprint ( GHCI_Customprint.hs, interpreted )
Ok, modules loaded: GHCI_Customprint.
*GHCI_Customprint> "blubb"
"blubb"
*GHCI_Customprint> [1..5]
[1,2,3,4,5]
*GHCI_Customprint> IntegerResult 39
39
*GHCI_Customprint> FloatingResult $ -236.24983e+89
-2.3624983e91

The other solution

As I said, you should be using a custom data type as your result, not Either. Why, if you have such a type you might as well give it a Show instance that does what you want:

instance Show CalcResult where
  show (IntegerResult intg) = show intg
  show (FloatingResult floatng) = show floatng

For your purposes, this will probably be just fine, you can use it in ghci without any extra tweaks and it does what you want. Only, there's a kind of law that a Show instance should produce valid Haskell code. But that's actually ok, because you can make 3 or 27.8 valid "constructors" for CalcResult!

instance Num CalcResult where
  fromInteger = IntegerResult
  IntegerResult a + IntegerResult b = IntegerResult $ a+b
  ...

instance Floating CalcResult where
  fromRational = FloatingResult . fromRational
  ...

Upvotes: 9

hammar
hammar

Reputation: 139890

When you evaluate this function, GHCi automatically calls putStrLn . show on the result. It is the show function for Either Integer Double which is adding the Left and Right strings.

To avoid this, you can use either show show instead, which will apply the show function only to the numbers stored inside the Either, so

> putStrLn . either show show $ calc ...

should give you what you want.

Upvotes: 9

Related Questions