我正在尝试将函数h映射到素数列表。两者都在下面给出:
f k x = floor ( log k / log x )
h = f 20
primes = 2 : sieve [3,5..]
where
sieve (p:xs) = p:[ x | x <- xs, x `mod` p > 0 ]
但是当我尝试map h primes
时,我收到以下错误:
Ambiguous type variable `a0' in the constraints:
(Enum a0)
arising from the arithmetic sequence `3, 5 .. '
依旧......
函数f和素数似乎都按预期工作但我不能将f应用于素数中的数字???我在这里误解了什么?
答案 0 :(得分:2)
您的函数primes
的类型为[Integer]
。
您的函数h
的类型为Double -> Integer
。
map
的类型是这样的:
ghci> :t map
map :: (a -> b) -> [a] -> [b]
或者当专门用于Integer
列表时,它的类型签名变为:
map :: (Integer -> b) -> [Integer] -> [b]
但是,您传递给h
的{{1}}函数的类型为map
,因此它没有进行类型检查,因为它期望Double -> Integer
而不是Integer -> b
功能接受Double
。
始终尝试在功能之前编写类型签名,这将使您的生活更轻松。
答案 1 :(得分:1)
primes :: Integral a => [a]
和h :: (RealFrac a, Integral b, Floating a) => a -> b
。现在,没有任何类型都是RealFrac
和Integral
的实例,但GHC并不知道这一点,因此它给出的错误消息有点令人困惑。
log :: Floating a => a -> a
,(/) :: Fractional a => a -> a -> a
和floor :: (RealFrac a, Integral b) => a -> b
,因此当我们撰写它们时,我们会获得上述类型的签名。 Haskell具有强大的数字类型,这意味着整数和浮点类型之间没有隐式转换。
使用显式转换函数fromIntegral :: (Integral a, Num b) => a -> b
:
map (h . fromIntegral) primes
答案 2 :(得分:0)
primes
有哪些类型?这完全取决于具体情况。它可能是
primes :: [Integer]
或其他。目前尚不清楚,因为像3
这样的文字具有类型3 :: Num a => a
。我们唯一可以肯定的是,无论需要什么样的Enum
实例,否则[3,5..]
都无法正常工作。
现在f
的类型是什么? f
在其参数上使用log
,然后将结果置于底层,因此我们可以期待类似
f :: (RealFrac a, Floating a, Integral b) => a -> a -> b
但是,这已经暗示您无法将其与map
一起使用,因为map
期望(a -> b)
作为第一个参数。更重要的是,primes
的元素不符合Floating
约束:
*Main> let (p1:p2:_) = primes
*Main> f p1 p2
<interactive>:29:1:
No instance for (RealFrac Integer) arising from a use of `f'
Possible fix: add an instance declaration for (RealFrac Integer)
In the expression: f p1 p2
In an equation for `it': it = f p1 p2
因此我们需要更改primes
类型或f
的类型。我们更改f
的类型:
f k x = floor ( log (fromIntegral k) / log (fromIntegral x) )
现在我们可以按预期使用f p1 p2
:
*Main> let (p1:p2:_) = primes
*Main> f p1 p2
0
但map
问题呢? map
期望(a -> b)
作为第一个参数,f
仍为(a -> b -> c)
*。从您当前的代码中,您似乎想要使用两个连续的素数并应用f
。为此,我们首先使用uncurry
:
uncurry :: (a -> b -> c) -> (a, b) -> c
现在uncurry f
有(a, b) -> c
。但现在列表(primes
)不是对列表。但是,我们可以很容易地解决这个问题,我们zip
用它的尾部填充:
map (uncurry f) (zip primes $ tail primes)
这就是如何在单个列表的连续元素上映射具有两个参数的函数。
* k或x可以是不同的积分类型