Haskell:如何停止程序打印左或右

时间:2013-04-28 20:10:55

标签: haskell types

我在haskell中制作了一个计算器,我在GHCi中运行。但是,由于最终的数字可以是整数或双数,所以我做了类型声明

calc :: String -> Either Integer Double

然而,函数的输出总是在它前面左侧或右侧,例如

Left 7

Right 8.4

有没有办法可以阻止左右打印?

2 个答案:

答案 0 :(得分:9)

奇特的方式

(可能下面另一个不那么花哨的解决方案对你来说更好)

如果你只关心ghci,那么现在(GHC> = 7.6)the possibility to use a custom print function。你只需指定

type CalcResult = Either Integer Double

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

然后通过

加载ghci
  

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

这样会有点烦人:calcPrint只能 使用CalcResult,因此您将无法显示任何其他内容。要解决这个问题,您可以使用类型类

{-# 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

这样您就可以按照自己喜欢的方式显示计算结果,以及旧Show类中的任何内容:

  

$ ghci-7.6 GHCI_Customprint.hs -interactive-print = GHCI_Customprint.calcPrint
  GHCi,版本7.6.2:http://www.haskell.org/ghc/ :?寻求帮助
  加载包ghc-prim ...链接...完成。
  加载包integer-gmp ...链接...完成。
  加载包基...链接...完成。
  [1 of 1]编译GHCI_Customprint(GHCI_Customprint.hs,解释)
  好的,模块加载: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

另一种解决方案

正如我所说,您应该使用自定义数据类型作为结果,而不是Either。为什么,如果你有这样的类型,你可以给它一个Show实例,做你想要的:

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

为了你的目的,这可能会很好,你可以在ghci中使用它而不需要任何额外的调整,它可以做你想要的。只有,Show实例应该生成有效的Haskell代码有一种规律。但这确实没问题,因为你可以为3制作27.8CalcResult个有效的“构造函数”!

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

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

答案 1 :(得分:9)

评估此功能时,GHCi会自动调用结果putStrLn . showshow的{​​{1}}函数正在添加Either Integer DoubleLeft字符串。

为避免这种情况,您可以使用Right代替,either show show功能仅将show功能应用于Either内存储的数字,所以

> putStrLn . either show show $ calc ...

应该给你你想要的东西。