Haskell:使用int签名整数到Int

时间:2015-10-29 18:32:36

标签: haskell integer int type-conversion

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

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 列出所有thoose特定的内部' S

此功能应该在以下列表中起作用:

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

我不允许在班级签名中使用整数,只有 Int 所以我不知道如何解决这个问题,我也不知道为什么会这样做说 firma 中的值整数

2 个答案:

答案 0 :(得分:5)

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

如果你的Haskell模块中有顶级定义,Haskell将推断单态类型,而不是多态。原因很简单。 Haskell假设经常使用顶级定义,如果表达式具有单形类型,则必须仅对其进行求值。在您的情况下,Haskell尝试为元组中的数字找到最合适的单态类型。通过规范/实现,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.在我看来,最后但相当昂贵的解决方案是手动将列表中的元素强制转换为首选类型。

答案 1 :(得分:3)

如果您可以更改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,您可以通过在listaOrdenado提示中为firma提供特定类型签名来致电ghci

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

如果firma实际上有使用Integer的类型签名,那么您需要使用IntegerInt投射到fromIntegral以某种方式:

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

然后在listaOrdenado中调用ghci

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