Как использовать памятку над последовательностью - PullRequest
0 голосов
/ 09 декабря 2018
let memoize (sequence: seq<'a>) =
    let cache = Dictionary()
    seq {for i in sequence -> 
         match cache.TryGetValue i with
         | true, v -> printf "cached"
         | false,_ -> cache.Add(i ,i)
    }

Я вызову свою функцию memoize внутри этой функции:

let isCached (input:seq<'a>) : seq<'a> = memoize input

Если данный элемент последовательности кэшируется, он должен печатать кэшированный, в противном случае он продолжит добавлять значение последовательности в кэш.

Сейчас у меня проблемы с типами.

Когда я пытаюсь вызвать мою функцию следующим образом:

let seq1 = seq { 1 .. 10 }
isCached seq1

Выдает ошибку

"The type int does not match the type unit"

Iхочу, чтобы моя функция работала универсально, даже если я возвращаю printfn.Можно ли этого добиться?И при добавлении значения в кеш уместно ли присвоить кортежу такое же значение?

например:

| false,_ -> cache.Add(i ,i)

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Томас П избил меня до удара, но я все равно опубликую это на всякий случай, если это поможет.

Я не слишком уверен, чего вы здесь добиваетесь, но я скажуНесколько вещей, которые, я думаю, могут помочь.

Во-первых, ошибка типа.Ваша функция isCached определяется как получение seq типа 'a и возвращение seq типа' a.Как написано в вашем вопросе, сейчас он принимает seq типа 'a и возвращает последовательность единиц измерения типа.Если вы попытаетесь изменить выходную спецификацию на seq <'b> (или на самом деле просто полностью опустите ее и сделаете так, чтобы это делало вывод типа), вы должны преодолеть ошибку типа.Это, вероятно, все еще не будет делать то, что вы хотите, так как вы на самом деле не возвращаете кеш из этой функции (вы можете просто добавить cache в качестве последней строки, чтобы вернуть его).Таким образом, попробуйте что-то вроде:

let memoize (sequence: seq<'a>) =
    let cache = Dictionary()
    for i in sequence do 
         match cache.TryGetValue i with
         | true, v -> printf "cached"
         | false,_ -> cache.Add(i ,i)

    cache

let isCached (input:seq<'a>) : seq<'b> = memoize input

Все это, как говорится, если вы собираетесь многократно повторять одну и ту же последовательность, лучше всего использовать библиотечную функцию Seq.cache .

Наконец, что касается использования значения в качестве ключа в словаре ... Ничто не мешает вам сделать это, но это действительно довольно бессмысленно.Если у вас уже есть значение, вам не нужно искать его в словаре.Если вы просто пытаетесь запомнить последовательность, используйте индекс данного элемента в качестве ключа.Или используйте конкретный вход в качестве ключа и выход из этого ввода в качестве значения.

0 голосов
/ 09 декабря 2018

Мне кажется, проблема в том, что ваша функция memoize фактически не возвращает элемент из исходной последовательности в качестве следующего элемента возвращаемой последовательности.Ваша версия только добавляет элементы в кеш, но затем возвращает unit.Вы можете исправить это, написав:

let memoize (sequence: seq<'a>) =
    let cache = Dictionary()
    seq {for i in sequence do
           match cache.TryGetValue i with
           | true, v -> printf "cached"
           | false,_ -> cache.Add(i ,i)
           yield i }

Я использовал явное yield вместо ->, потому что я думаю, что это делает код более читабельным.С этим изменением код запускается для меня как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...