Ambigous类型变量

der*_*_tj 2 haskell type-constraints

我写了一个小的haskell程序,只计算一个数字(Int)中有多少个.当我尝试执行时,haskell抱怨有关变量的约束.我知道它来自使用地板.我还阅读了stackoverflow上的一些答案.但我并没有找到解决方法.这是我的代码:

count_ones = count_ones' 0

count_ones' m 0 = m
count_ones' m n | n-10*n_new == 1 = count_ones' (m+1) n_new
                | otherwise         = count_ones' m n_new
                 where n_new = floor (n/10)
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Dan*_*her 5

count_ones' m n | n-10*n_new == 0.1 = count_ones' (m+1) n_new
                | otherwise         = count_ones' m n_new
                 where n_new = floor (n/10)
Run Code Online (Sandbox Code Playgroud)

在第一行中,您将n - 10*n_new与小数字面值进行比较0.1,因此类型nn_new必须是Fractional类的成员.

where子句中,绑定n_new = floor (n/10),因此类型n_new必须是Integral类的成员.

由于没有标准类型是两个类的成员(出于好的理由),编译器无法解析约束

(Fractional a, Integral a) => a
Run Code Online (Sandbox Code Playgroud)

当函数被调用时.

如果为函数提供类型签名,编译器通常可以生成更多有用的错误消息.

您的问题,最简单的解决方法是改变的结合n_new

n_new = fromIntegral (floor $ n/10)
Run Code Online (Sandbox Code Playgroud)

考虑到在评论中你说这0.1是一个错误而你应该使用它1,你可能只想使用Integral类型,你的代码最接近的转录将是

count_ones' :: Integral a => Int -> a -> Int
count_ones' m 0 = m
count_ones' m n
    | n - 10*n_new == 1 = count_ones' (m+1) n_new
    | otherwise         = count_ones' m n_new
      where
        n_new = n `div` 10
Run Code Online (Sandbox Code Playgroud)

但它可能是更清晰的更换条件n - 10*n_new == 1n `mod` 10 == 1.

但是,这将需要每步两个分区,这可能效率较低.使用时divMod应该只用一条除法指令给你除数和余数,

count_ones' m n = case n `divMod` 10 of
                    (q,1) -> count_ones' (m+1) q
                    (q,_) -> count_ones' m q
Run Code Online (Sandbox Code Playgroud)

如果你可以保证你只会用非负数调用这个函数n,请使用quotremresp.quotRem而不是divmodresp.divMod.前者的功能直接使用机器分割指令的结果,而后者需要一些后处理才能确保结果mod是非负的,所以quot和朋友比div公司更有效率.