繁体   English   中英

Haskell中的Num类型类操作?

[英]Num type class operations in Haskell?

我正在尝试用Haskell写一个口译员(确切地说,我正在看《 48小时内将自己写成一个方案》)。 我尝试将浮点运算添加到解释器。 现在,我有以下代码:

data LispVal = Number Integer
             | Float Float
             deriving(Show, Eq)

doNumeric :: (Num a) => (a -> a -> a) -> LispVal -> LispVal -> LispVal
doNumeric op (Number a) (Number b) = Number $ a `op` b
doNumeric op (Float a) (Number b) = Float $ a `op` (fromIntegral b)
doNumeric op (Number a) (Float b) = Float $ (fromIntegral a) `op` b
doNumeric op (Float a) (Float b) = Float $ a `op` b

通过这种方式,我希望仅通过以下方式构造数字运算,如加,减,乘和除:doNumeric(+),doNumeric(-)..等,这样我就无需为doMul,doAdd等编写代码。

但是对于上面的代码,GHC抱怨:

Couldn't match type `Integer' with `Float'
Expected type: a
  Actual type: Float
In the first argument of `op', namely `a'
In the second argument of `($)', namely `a `op` (fromIntegral b)'
In the expression: Float $ a `op` (fromIntegral b)

因此,如果我希望op进行Num类型类中存在的操作,该怎么办? 如何进行上述代码类型检查?

问题是您正在尝试将类型a -> a -> a op a -> a -> a的函数op应用于特定类型。 您的签名说的是“ op特定类型a上的二进制运算符”。 也就是说, a由传入的函数确定,它可能不是IntegerFloat (GHC在第二个定义中给出警告,这有点奇怪,但是如果您注释掉后三个定义,则仅doNumeric为两个Number定义doNumeric时也会看到它。)

使用op的方式,您确实需要2级类型:

{-# LANGUAGE RankNTypes #-}

doNumeric :: (forall a . (Num a) => a -> a -> a) -> LispVal -> LispVal -> LispVal
doNumeric op (Number a) (Number b) = Number $ a `op` b
...

这意味着op保证可以用于任何 Num type a ,我怀疑这是您要的。 因此,您可以使用(+)来调用doNumeric ,但是不能使用f :: Int -> Int -> Int doNumeric f :: Int -> Int -> Int来调用doNumeric

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM