Как запретить этой циклической полиномиальной хеш-функции использовать ограничение типа?

Я пытаюсь реализовать циклическую полиномиальную хэш-функцию в 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

Моя проблема в том, что тип 'a будет ограничен intв то время как я хочу, чтобы эта функция работала с любыми типами, которые работают с побитовыми операторами, например char, Я пытался с помощью inline, но это создает некоторые проблемы в моей библиотеке. Есть ли способ исправить это без использования inline?

Правка для ясности: эта функция будет частью библиотеки, а для типов, не поддерживающих побитовые операторы, предусмотрена другая хеш-функция. Я хочу, чтобы эта функция работала с массивами числовых типов и / или символов.

Редактировать 2 (проблема решена): проблема с inline была в том, как я загружал функцию из моей библиотеки. вместо

let hashedPattern = library.createBuzhash targetPattern

Я использовал эту привязку:

let myFunction = library.createBuzhash
let hashedPattern = myFunction targetPattern

что ограничивает тип ввода для myFunction к инт, хотя createBuzhash функция является inline функция в библиотеке. Изменение способа вызова функции решило проблему ограничения типа и inline работает отлично, как предполагает ответ ниже.

1 ответ

Решение

В реализации вы конвертируете значение в массиве в целое число, используя int функционировать следующим образом: int pattern.[index]

Это создает ограничение на тип элементов массива, требующих, чтобы они были "чем-то, что может быть преобразовано в int". Если вы отметите функцию как inline, это на самом деле будет работать для таких типов, как char и вы сможете написать:

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

Но есть еще много других типов, которые не могут быть преобразованы в целое число с помощью int функция.

Чтобы заставить это работать для любого типа, вы должны решить, как вы хотите обрабатывать типы, которые не являются числовыми. Хотите ли вы:

  • Предоставить свою собственную функцию хеширования для всех значений?
  • Используйте встроенный.NET 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 функция:

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

Но вы также можете использовать встроенный механизм хеширования F#:

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

И вы даже можете обрабатывать вложенные массивы, передавая функцию себе:

createBuzhash (createBuzhash int) [| [| 1 |]; [| 2 |] |]
Другие вопросы по тегам