2

我正在尝试在 f#中实现循环多项式哈希函数。它使用按位运算符 ^^^ 和 <<<。下面是一个散列数组的函数示例:

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

我的问题是 of 的类型'a将被限制为 a int,而我希望此函数与任何可与按位运算符一起使用的类型一起使用,例如 a char。我尝试使用inline,但这会在我的库中产生一些问题。有没有办法在不使用的情况下解决这个问题inline

为清楚起见进行编辑:该函数将成为库的一部分,并且为不支持按位运算符的类型提供了另一个哈希函数。我希望这个函数可以处理数字类型和/或字符的数组。

编辑 2(问题已解决):内联的问题是我从库中加载函数的方式。代替

let hashedPattern = library.createBuzhash targetPattern

我使用了这个绑定:

let myFunction = library.createBuzhash
let hashedPattern = myFunction targetPattern

尽管该函数是库中的函数,但它将输入类型限制为myFunctionint 。改变我调用函数的方式修复了类型约束问题,并且工作得很好,如下面的答案所示。createBuzhashinlineinline

4

1 回答 1

3

在实现中,您使用以下函数将数组中的值转换为整数intint pattern.[index]

这对数组元素的类型产生了限制,要求它们是“可以转换为int”的东西。如果您将函数标记为inline,它实际上将适用于类似的类型char,您将能够编写:

createBuzhash [|'a'; 'b'|]

但仍有许多其他类型无法使用该int函数转换为整数。

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

  • 为所有值提供您自己的散列函数?
  • 使用内置的.NETGetHashCode操作?
  • 仅使您的函数适用于数字类型和数字类型的数组?

一种选择是添加一个指定如何进行转换的参数:

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这适用于使用函数的原始类型:

createBuzhash int [| 0 .. 10 |]
createBuzhash int [|'a'; 'b'|]

但您也可以使用内置的 F# 散列机制:

createBuzhash hash [| (1,"foo"); (2,"bar") |]

您甚至可以通过将函数传递给自身来处理嵌套数组:

createBuzhash (createBuzhash int) [| [| 1 |]; [| 2 |] |]
于 2016-09-27T14:32:57.320 回答