如何防止这个循环多项式散列函数使用类型约束?

时间:2016-09-27 14:21:11

标签: hash f# type-conversion constraints rabin-karp

我正在尝试在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完全正常,如下面的答案所示。

1 个答案:

答案 0 :(得分:3)

在实现中,您使用build.gradle函数将数组中的值转换为Integer,如下所示:int

这会对数组元素的类型产生约束,要求它们是可以转换为int pattern.[index]&#34;的东西。如果您将该功能标记为int,它实际上适用于inline等类型,并且您可以写下:

char

但仍有许多其他类型无法使用createBuzhash [|'a'; 'b'|] 函数转换为整数。

要使其适用于任何类型,您必须决定如何处理非数字类型。你想要:

  • 为所有值提供自己的哈希函数?
  • 使用内置的.NET 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") |]