【问题标题】:Haskell : Integer to Int with int signatureHaskell:整数到带有 int 签名的 Int
【发布时间】:2016-01-30 01:22:04
【问题描述】:

所以我遇到了一些变量类型的问题。

getOrdenado :: (String,Int,String,Int,Int) -> Int
getOrdenado (_,_,_,a,_) = a 

listaOrdenado :: [(String,Int,String,Int,Int)] -> [Int]
listaOrdenado xs = map getOrdenado xs

getOrdenado 从包含在元组列表中的元组中获取某个 Int 值,listaOrdenado 列出所有这些特定的 int。

这个函数应该在以下列表上工作:

firma = [("Ana", 30, "RH", 1500, 3), ("Rui", 40, "Vendas", 1000, 2),
        ("Luis", 45, "RH", 3333, 5), ("Maria", 55, "Admin", 2000, 4)]

但每当我尝试使用此列表运行 listaOrdenado 时,我都会收到以下错误

Couldn't match type `Integer' with `Int'
Expected type: [(String, Int, String, Int, Int)]
  Actual type: [([Char], Integer, [Char], Integer, Integer)]
In the first argument of `listaOrdenado', namely `firma'
In the expression: listaOrdenado firma
In an equation for `it': it = listaOrdenado firma

我不允许在类签名中使用 Integer,只能使用 Int 所以我不知道如何解决这个问题,也不知道为什么会这样表示 firma 中的那些值是 Integer

【问题讨论】:

  • 您可以通过将30 :: Int 之类的内联类型强制Int 作为类型,或者给firma 一个类型签名,以便它使用Int 而不是Integer (Integer是默认值)
  • 尝试将firma :: [(String, Int, String, Int, Int)] 放在firma 的声明之前。如果您在 GHCi 中定义它,则将其放入文件中。
  • 我不能给 firma 任何签名,更具体地说,我不能改变任何关于 firma
  • 那么无论您在代码中使用 firma 的任何位置,都可以像这样引用它:(firma :: [(String, Int, String, Int, Int)])
  • 所以我应该将此行添加到我的代码中:

标签: haskell integer int type-conversion


【解决方案1】:

由于问题尚未解决,我将答案编辑得更准确:

如果您的 Haskell 模块中有顶级定义,Haskell 将推断出 单态 类型而不是多态。原因很简单。 Haskell 假设一个顶级定义经常被使用,如果一个表达式有一个单态类型,它必须被评估为一个。在您的情况下,Haskell 尝试为您的元组中的数字找到最合适的 monomorphic 类型。根据规范/实现,Haskell 首先尝试Integer 类型,然后尝试Float 类型。这就是代码中出现类型错误的原因。

现在你有几个选项来解决这个问题:

1.在您的模块中添加firma的类型(首选解决方案):

module Test where

getOrdenado :: (String,Int,String,Int,Int) -> Int
getOrdenado (_,_,_,a,_) = a 

listaOrdenado :: [(String,Int,String,Int,Int)] -> [Int]
listaOrdenado xs = map getOrdenado xs

firma :: Num a => [(String,a,String,a,a)]
firma = [("Ana", 30, "RH", 1500, 3), ("Rui", 40, "Vendas", 1000, 2),
        ("Luis", 45, "RH", 3333, 5), ("Maria", 55, "Admin", 2000, 4)]

如果你打电话给listaOrdenado firma,对我来说效果很好。

2.第二种可能性是通过覆盖使用的默认值来关闭单态类型推断。这个 wiki 条目解释了这是如何完成的:https://wiki.haskell.org/Monomorphism_restriction

3.在我看来,最后但相当昂贵的解决方案是将列表中的元素手动转换为首选类型。

【讨论】:

  • 在使用现场标注只会移动类型错误。
  • 将此行添加到我的代码后:firma :: Num a, Num b, Num c => [(String, a, String, b, c)] 尝试执行以下操作时出现以下错误将我的 .hs 文件加载到 ghci: .hs:1:15: parse error on input `,' caracter 15 is the first , after a
  • 抱歉,这是复制粘贴错误,我更新了答案。
  • 解析错误消失了,但现在它给出了另一个关于缺少伴随绑定的错误:“firma”的类型签名缺少伴随绑定
  • 你能解释一下你是如何使用firma的吗?您是否尝试手动投射它,然后出现此错误?
【解决方案2】:

如果您可以更改firma的签名,只需为其添加适当的类型签名即可:

firma :: [(String, Int, String, Int, Int)]
firma = [("Ana", 30, "RH", 1500, 3), ("Rui", 40, "Vendas", 1000, 2),
        ("Luis", 45, "RH", 3333, 5), ("Maria", 55, "Admin", 2000, 4)]

如果不允许更改 firma,您可以通过在 ghci 提示符上为 firma 指定特定类型签名来调用 listaOrdenado

$ ghci firma.hs
λ> listaOrdenado (firma :: [(String, Int, String, Int, Int)])

如果firma 实际上有一个使用Integer 的类型签名,那么您需要以某种方式使用fromIntegralInteger 转换为Int

fI = fromIntegral
integerToInt [] = []
integerToInt ((a,b,c,d,e):xs) = (a, fI b, c, fI d, fI e) : (integerToInt xs)

然后像这样在ghci 中调用listaOrdenado

$ ghci firma.hs
λ> listaOrdenado (integerToInt firma)

【讨论】:

  • 问题是firma 是一个列表,将用于测试我的代码,firma 的元组可能比我提供的要多,唯一确定的是内部变量的类型元组。所以我不能喜欢在我的 . Hs 文件也不能在为 ghci 调用它时添加规范,因为在评估函数时我不会是调用她的人。而且我相信firma 没有签名,或者至少我没有得到签名
  • 如果你不是调用listaOrdenado的人,并且不允许在类型签名中使用IntegerNum,那么你可以假设使用你的代码的人都会通过正确的类型,因为调用者有责任提供正确的类型,因为 Haskell 是强类型的。
猜你喜欢
  • 1970-01-01
  • 2010-09-24
  • 2012-06-13
  • 2019-09-30
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多