4

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

calc :: String -> Either Integer Double

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

Left 7

Right 8.4

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

4

2 回答 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,版本 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
  ...
于 2013-04-28T20:19:44.607 回答
9

当你评估这个函数时,GHCi 会自动调用putStrLn . show结果。它是添加和字符串的show函数。Either Integer DoubleLeftRight

为避免这种情况,您可以either show show改用,它将仅将show函数应用于存储在 中的数字Either,因此

> putStrLn . either show show $ calc ...

应该给你你想要的。

于 2013-04-28T20:23:21.540 回答