Haskell:如何停止程序打印 Left 或 Right

4

我在Haskell中制作了一个计算器,我从GHCi中运行它。然而,由于最终数字可以是整数或双精度浮点数,因此我进行了类型声明。

calc :: String -> Either Integer Double

然而,该函数的输出始终在其前面添加左侧或右侧,例如:
Left 7

Right 8.4

有没有办法停止打印左右两侧的内容?
2个回答

9

高级方法

(也许,下面的另一种不那么高级的解决方案更适合您)

如果您只关心ghci,现在(GHC>=7.6)有使用自定义打印函数的可能性。您只需指定:

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, 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

另一种解决方案

正如我所说,您应该使用一个自定义数据类型作为结果,而不是Either。如果您有这样的类型,那么您可能会给它一个Show实例来完成您想做的事情:

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

对于您的目的,这可能就足够了,您可以在ghci中使用它而不需要任何额外的调整,并且它可以完成您想要的工作。只是,有一种法律规定Show实例应该生成有效的Haskell代码。但这实际上是可以的,因为您可以为CalcResult创建327.8有效的“构造函数”!

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

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

9
当你评估这个函数时,GHCi会自动在结果上调用putStrLn . show。它是用于Either Integer Doubleshow函数,该函数将添加LeftRight字符串。
为了避免这种情况,您可以使用either show show,它仅将show函数应用于Either中存储的数字,因此
> putStrLn . either show show $ calc ...

应该能给您想要的东西。


3
更好的是,定义自己的打印函数:p = putStrLn . either show show - Gabriella Gonzalez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接