gpt4 book ai didi

haskell - 编写 binop 来处理 int 和 float

转载 作者:行者123 更新时间:2023-12-02 12:04:04 27 4
gpt4 key购买 nike

我正在开发一个解析器。在不了解所有细节的情况下,我想要一个将两个数值相加的函数:

add [VFloat a, VFloat b] = return $ VFloat (a + b)
add [VInt a, VFloat b] = return $ VFloat (fromInteger a + b)
add [VFloat a, VInt b] = return $ VFloat (a + fromInteger b)
add [VInt a, VInt b] = return $ VInt (a + b)
add [_,_] = throwError "Currently only adding numbers"
add _ = throwError "Arity Error: Add takes 2 arguments"

酷,效果很好。现在我想要 - 具有相同的功能, * , / , < , > , ==等等...

所以我分解出+运算符并转到传入运算符 op :: Num a => a->a->a对吗?

嗯,不完全是。如果我只是替换 +'op'类型检查器告诉我 op 实际上是 Double -> Double -> Double基于前三个版本,因此它不能应用于 Integer第四个版本。

两个问题:

  1. 我该怎么写binop :: Num a => (a->a->a) -> [Value]-> EvalM Value这样它就可以同时处理 VInt 和 VFloat 了?
  2. 我所面临的情况的正确名称是什么,以便我下次可以通过 Google 搜索找到答案?

最佳答案

这称为higher rank types ,基本上你想要的类型是

 binop :: (forall a. Num a => a -> a -> a) -> [Value] -> EvalM Value

但是你拥有的是

 binop :: forall a. Num a => (a -> a -> a) -> [Value] -> EvalM Value

你看出区别了吗?对于第一个函数,运算符实际上在函数内是多态的,它表示“给定一个函数,它接受任何类型为 a -> a -> aNum a .. .”。第二个说,“对于所有 a,给定来自单个任意 a -> a -> a ... 的函数”。

幸运的是,GHC 支持更高级别的类型,

{-# LANGUAGE RankNTypes #-}

...
binop :: (forall a. Num a => a -> a -> a) -> [Value] -> EvalM Value
binop (+) [VFloat a, VFloat b] = return $ VFloat (a + b)
binop (+) [VInt a, VFloat b] = return $ VFloat (fromInteger a + b)
binop (+) [VFloat a, VInt b] = return $ VFloat (a + fromInteger b)
binop (+) [VInt a, VInt b] = return $ VInt (a + b)
binop _ [_,_] = throwError "Currently only adding numbers"
binop _ _ = throwError "Arity Error: Add takes 2 arguments"

但是,类型推断器对于较高级别的类型并不那么热衷,因此您可能必须添加显式签名。

关于haskell - 编写 binop 来处理 int 和 float,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20367000/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com