我正在尝试在f#中实现Cyclic polynomial hash function。它使用逐位运算符^^^和<<<。以下是散列数组的函数示例:
let createBuzhash (pattern : array<'a>) =
let n = pattern.Length
let rec loop index pow acc =
if index < n then
loop (index+1) (pow-1) (acc ^^^ ((int pattern.[index]) <<< pow))
else
acc
loop 0 (n-1) 0
我的问题是'a
的类型将被约束为int
,而我希望此函数适用于与逐位运算符一起使用的任何类型,例如{ {1}}。我尝试使用char
,但这会在我的库中产生更多问题。有没有办法解决这个问题而不使用inline
?
编辑:该函数将成为库的一部分,并且为不支持逐位运算符的类型提供另一个散列函数。我希望这个函数能够处理数值类型和/或字符数组。
编辑2(问题解决了):内联的问题是我从库中加载函数的方式。而不是
inline
我使用了这个绑定:
let hashedPattern = library.createBuzhash targetPattern
将let myFunction = library.createBuzhash
let hashedPattern = myFunction targetPattern
的输入类型约束为int,尽管myFunction
函数是库中的createBuzhash
函数。改变我调用函数的方式修复了类型约束问题,inline
完全正常,如下面的答案所示。
答案 0 :(得分:3)
在实现中,您使用build.gradle
函数将数组中的值转换为Integer,如下所示:int
这会对数组元素的类型产生约束,要求它们是可以转换为int pattern.[index]
&#34;的东西。如果您将该功能标记为int
,它实际上适用于inline
等类型,并且您可以写下:
char
但仍有许多其他类型无法使用createBuzhash [|'a'; 'b'|]
函数转换为整数。
要使其适用于任何类型,您必须决定如何处理非数字类型。你想要:
int
操作?一个选项是添加一个指定如何进行转换的参数:
GetHashCode
调用let inline createBuzhash conv (pattern : array<'a>) =
let n = pattern.Length
let rec loop index pow acc =
if index < pattern.Length then
loop (index+1) (pow-1) (acc ^^^ ((conv pattern.[index]) <<< pow))
else
acc
loop 0 (n-1) 0
时,您现在需要为其提供散列元素的函数。这适用于使用createBuzhash
函数的原始类型:
int
但您也可以使用内置的F#散列机制:
createBuzhash int [| 0 .. 10 |]
createBuzhash int [|'a'; 'b'|]
您甚至可以通过将函数传递给自身来处理嵌套数组:
createBuzhash hash [| (1,"foo"); (2,"bar") |]