【问题标题】:Getting the error "Non type-variable argument in the constraint: Integral [a2]"收到错误“约束中的非类型变量参数:积分 [a2]”
【发布时间】:2018-09-09 19:25:20
【问题描述】:

我正在尝试使用以下代码实现 luhn 算法:

luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (read x :: Int)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
    where
        doEncrypt (i,y) acc = if not(even i)
            then head(((uncurry (+) . (`divMod` 10) . (*2)) y)) : acc
            else (head y) : acc

我现在遇到以下错误:

• Non type-variable argument in the constraint: Integral [a2]
  (Use FlexibleContexts to permit this)
• When checking the inferred type
    doEncrypt :: forall a1 a2.
                 (Integral a1, Integral [a2]) =>
                 (a1, [a2]) -> [a2] -> [a2]
  In an equation for ‘luhn’:
      luhn x
        = (tail
             $ show
                 (foldl
                    (\ acc x -> acc + (read x :: Int))
                    0
                    (foldr doEncrypt [] $ zip [0 .. ] (show x))))
            == "0"
        where
            doEncrypt (i, y) acc
              = if not (even i) then
                    head (((uncurry (+) . (`divMod` 10) . (* 2)) y)) : acc
                else
                    (head y) : acc

我看到错误表明元组的第二部分 (a2) 是“非类型变量参数”。然而,Haskell 似乎将此a2 参数识别为Integral,而实际上它是Char。我如何告诉 Haskell 这是一个 Char 并且 Haskell 不应该再担心这个变量的类型?还是有什么我不明白的原因导致了这个错误?

编辑: 当我删除 (head y) 并将其替换为 y 时,我得到以下错误:

• Couldn't match type ‘Char’ with ‘[Char]’
  Expected type: [String]
    Actual type: [Char]
• In the third argument of ‘foldl’, namely
    ‘(foldr doEncrypt [] $ zip [0 .. ] (show x))’
  In the first argument of ‘show’, namely
    ‘(foldl
        (\ acc x -> acc + (read x :: Int))
        0
        (foldr doEncrypt [] $ zip [0 .. ] (show x)))’
  In the second argument of ‘($)’, namely
    ‘show
       (foldl
          (\ acc x -> acc + (read x :: Int))
          0
          (foldr doEncrypt [] $ zip [0 .. ] (show x)))’

【问题讨论】:

  • 由于你使用(head y),这意味着y应该是一个列表,但在函数体的其他部分,你使用y作为一个数字(进行计算)。结果是Haskell认为列表应该是数字,所以报错。
  • @WillemVanOnsem 感谢您的回复。我试过了,但这会导致另一个我不理解的错误,并且我无法在 Google 上找到有关信息(我将其附加到我的问题中)。
  • 我认为你应该在第一个子句中添加一个head,以及一个read。但话虽如此。这看起来很“混乱”。即使它后来“产生了答案”,也很难“说服”同行该算法正常工作。所以我认为实施 cleaner 解决方案可能会更好。
  • @WillemVanOnsem 这实际上帮助我解决了它。谢谢!

标签: haskell fold accumulator


【解决方案1】:

我的解决方案有很多问题,但最后下面的代码可以工作!

luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (digitToInt x)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
    where
        doEncrypt (i,y) acc = if not(even i)
            then (head $ show(((uncurry (+) . (`divMod` 10) . (*2)) (digitToInt y)))) : acc
            else y : acc

非常感谢@WillemVanOnsem 的指点,如果没有我可能无法解决这个问题!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多