Haskell : Integer to Int with int signature

Haskell : Integer to Int with int signature

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

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

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

getOrdenado 从包含在元组列表中的元组和 listaOrdenado[=33] 中获取某个 Int 值=]列出所有特定的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

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

如果可以更改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 的类型签名,那么您需要使用 fromIntegral 以某种方式从 Integer 转换为 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)

由于问题还没有解决,我把我的答案编辑得更准确:

如果您的 Haskell 模块中有顶级定义,Haskell 将推断出 单态 类型而不是多态。原因很简单。 Haskell 假设顶层定义被经常使用,并且如果表达式具有单态类型,则必须仅对其求值。在您的情况下,Haskell 尝试为元组中的数字找到最合适的 monomorphic 类型。通过 specification/implementation Haskell 首先尝试类型 Integer,然后尝试类型 Float。这就是您的代码中出现类型错误的原因。

现在您有几种选择来解决这个问题:

1.Add你模块中的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.The 第二种可能性是通过覆盖使用的默认值来关闭单态类型推断。这个 wiki 条目解释了这是如何完成的:https://wiki.haskell.org/Monomorphism_restriction

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