Haskell 生成范围条件时类型不匹配

Haskell 生成范围条件时类型不匹配,haskell,types,type-conversion,Haskell,Types,Type Conversion,我正在解决我在互联网上发现的一个有趣的haskell练习,因此我对下面的代码进行了中性化,以仍然按类型复制错误,但不显示任何类型的解决方案: import Control.Monad import Data.List(permutations) permutationsUpTo :: Int -> [a] -> [[a]] permutationsUpTo 0 _ = [] permutationsUpTo _ [] = [] permutationsUpTo n (x:xs) =

我正在解决我在互联网上发现的一个有趣的haskell练习,因此我对下面的代码进行了中性化,以仍然按类型复制错误,但不显示任何类型的解决方案:

import Control.Monad
import Data.List(permutations)

permutationsUpTo :: Int -> [a] -> [[a]]
permutationsUpTo 0 _ = []
permutationsUpTo _ [] = []
permutationsUpTo n (x:xs) = (permutationsUpTo (n) (xs)) ++ permutations (x:xs)

-- function borrowed from rosetta code
nthRoot n x = fst $ until (uncurry(==)) (\(_,x0) -> (x0,((n-1)*x0+x/x0**(n-1))/n)) (x,x/n)

integerNthRoot n = ceiling . (nthRoot n) . fromIntegral

algorithm :: Int -> Int -> [[Int]]
algorithm x n = do
    perm <- permutationsUpTo x [1..(integerNthRoot n x)]
    guard ((sum perm) == x)
    return perm
import-Control.Monad
导入数据列表(排列)
置换supto::Int->[a]->[a]]
置换到0=[]
排列supto[]=[]
置换supto n(x:xs)=(置换supto(n)(xs))++置换(x:xs)
--从rosetta代码中借用的函数
n根nx=fst$uncurry(=)(\(\,x0)->(x0,((n-1)*x0+x/x0**(n-1))/n))(x,x/n)
整数throot n=天花板。(n)。从积分
算法::Int->Int->[[Int]]
算法xn=do

perm算法的类型签名
n
的类型固定为
Int
,因此需要
nthRoot(从整数n开始)


(为Haskell中的所有顶级内容提供类型签名确实非常有帮助,即使您没有尝试调试类型错误。)

问题来自于您的Rosetta代码。如果检查GHCi中的
nthRoot
类型,则为

nthRoot :: (Eq a, Fractional a) => a -> a -> a
但你真正想要的是

nthRoot :: (Integral a, Eq b, Floating b) => a -> b -> b
如果添加该类型签名,则错误来自
n
x
x0
之间的算术运算。一个简单的解决方案:

nthRoot :: (Integral a, Eq b, Floating b) => a -> b -> b
nthRoot n x = fst $ until (uncurry (==)) (\(_, x0) -> (x0, ((n' - 1) * x0 + x / x0 ** (n' - 1)) / n')) (x, x / n')
    where n' = fromIntegral n
然后您的
integerntroot
函数具有

integerNthRoot :: (Integral a, Integral b, Integral c) => a -> b -> c
算法
类型检查

您应该始终将类型签名添加到顶级声明中。它会帮你捉虫子的


由于在
nthRoot
中有
Eq b和浮动b
,因此最好改用
Double
(hlint建议)。那你就只有

nthRoot :: Integral a => a -> Double -> Double
nthRoot = ...
我注意到你可能更愿意

integerNthRoot :: (Integral a, Integral b) => a -> b -> b
integerNthRoot = ...

我通常会添加类型签名,但一开始我甚至不确定我想要的是什么类型!谢谢你的意见。这是你发现问题的第一个指标!谢谢是的,我试图在我所有的声明中添加类型,但在这种情况下(因为我从rosetta代码中获得了一个函数),我不确定我需要什么类型。顺便说一句,我相信你的意思是在你建议的第二个类型声明中写
浮动b
。@LevDubinets现已修复!
integerNthRoot :: (Integral a, Integral b) => a -> b -> b
integerNthRoot = ...