我正在尝试用数组记住这个函数:
a n 0 = n
a n k = a (2*n - 1) (k - 1) / a (2*n) (k - 1)
我做到了这一点:
import Data.Array
cache :: (Ix a, Real b) => Array a [(a, b)]
cache = array bounds [(i, func i) | i <- range bounds]
where bounds = ((0,0), (1000, 1000))
func elem =
let f n 0 = n
f n k = f (2*n - 1) (k - 1) / f (2*n) (k - 1)
in uncurry f elem
a n k = cache!(n,k)
GHCi因此错误而失败:
aarr.hs:6:16:
Could not deduce (a ~ ([(a, b)], b0))
from the context (Ix a, Real b)
bound by the type signature for
values :: (Ix a, Real b) => Array a [(a, b)]
at aarr.hs:5:11-44
‘a’ is a rigid type variable bound by
the type signature for values :: (Ix a, Real b) => Array a [(a, b)]
at aarr.hs:5:11
Expected type: (a, a)
Actual type: (([(a, b)], b0), ([(a, b)], b0))
Relevant bindings include
bounds :: (([(a, b)], b0), ([(a, b)], b0)) (bound at aarr.hs:7:11)
values :: Array a [(a, b)] (bound at aarr.hs:6:1)
In the first argument of ‘array’, namely ‘bounds’
In the expression: array bounds [(i, func i) | i <- range bounds]
我头脑中的所有类型错误(以及无限类型错误)都在旋转......我认为这可行。
答案 0 :(得分:3)
您的cache
功能存在两个问题,导致无法编译。
第一个是(/)
的类型如下,
(/) :: Fractional a => a -> a -> a
然而,编译器会将bounds
中的值推断为Integral
类型,这与使用/
时不相符。
第二个是您的类型签名不正确。
有很多方法可以解决这个问题,但最简单的可能是以下几点,
cache :: (Ix b, Fractional b) => Array (b, b) b
cache = array bounds [(i, func i) | i <- range bounds]
where bounds = ((0.0,0.0), (1000.0, 1000.0))
func elem =
let f n 0 = n
f n k = f (2*n - 1) (k - 1) / f (2*n) (k - 1)
in uncurry f elem
请注意,bounds
的值现在是Fractional
值。
另请注意,我更改了您的类型签名。 Array
的第一个类型参数必须是Ix
实例。由于您使用Fractional
对作为索引,因此需要在类型中反映出来。其次,这也意味着数组中元素的值与索引共享相同的类型。如果您希望索引为积分值,则可以执行以下操作,
cache :: (Integral a, Ix a, Fractional b) => Array (a, a) b
cache = array bounds [(i, func i) | i <- range bounds]
where bounds = ((0,0), (1000, 1000))
func (a, b) =
let f n 0 = n
f n k = f (2*n - 1) (k - 1) / f (2*n) (k - 1)
in uncurry f (fromIntegral a, fromIntegral b)
注意,我不知道是否使用Integral
类型与Fractional
类型,因为索引有任何性能方面的考虑,因为我不经常使用Array
类型