У меня есть рекурсивная функция f
, которая принимает два параметра x
и y
. Функция однозначно определяется первым параметром; второй просто облегчает ситуацию.Памятка с дополнительным параметром в Haskell
Теперь я хочу сохранить меморандум о том, что функция w.r.t. это первый параметр, игнорируя второй. (I.e. f
оценивается не более одного для каждого значения x
)
Что такое самый простой способ сделать это? На данный момент я просто определяю массив, содержащий все значения, рекурсивно, но это несколько ad-hoc-решение. Я бы предпочел какой-то комбинатор memoisation, который я могу просто бросить в свою функцию.
EDIT: для уточнения функции f
берет пару целых чисел и список. Первое целое число - это некоторое значение параметра, второе - индекс элемента в некотором глобальном списке xs
для потребления.
Чтобы избежать индексации списка, я прохожу частично потребленной список f
как хорошо, но, очевидно, инвариант в том, что, если первый параметр (m, n)
, второй всегда будет drop n xs
, поэтому результат однозначно определяется первый параметр.
Просто использование комбинатора memoisation на частично примененной функции не будет работать, так как это оставит неоценимый thunk \xs -> …
, лежащий вокруг. Я мог бы, вероятно, обернуть два параметра в виде данных, чей экземпляр Eq
игнорирует второе значение (и аналогично для других экземпляров), но это похоже на очень специальное решение. Нет ли более простого способа?
EDIT2: Конкретная функция Я хочу memoise:
g :: [(Int, Int)] -> Int -> Int
g xs n = f 0 n
where f :: Int -> Int -> Int
f _ 0 = 0
f m n
| m == length xs = 0
| w > n = f (m + 1) n
| otherwise = maximum [f (m + 1) n, v + f (m + 1) (n - w)]
where (w, v) = xs !! m
Чтобы избежать дорогостоящей операции индексирования, я вместо того, чтобы передать частично потребленной список f
, а также:
g' :: [(Int, Int)] -> Int -> Int
g' xs n = f xs 0 n
where f :: [(Int, Int)] -> Int -> Int -> Int
f [] _ _ = 0
f _ _ 0 = 0
f ((w,v) : xs) m n
| w > n = f xs (m + 1) n
| otherwise = maximum [f xs (m + 1) n, v + f xs (m + 1) (n - w)]
мемоизация из f
wrt параметр списка, конечно, не нужен, поскольку список не влияет (нравственно) на результат. Поэтому мне хотелось бы, чтобы воспоминание просто игнорировало параметр списка.
Вы еще посмотрели [Haskell Wiki on Memoization] (https://wiki.haskell.org/Memoization)? - Кроме того, это, вероятно, поможет увидеть вашу функцию (или, по крайней мере, подпись), также если вам нужен только второй параметр внутри, вы должны скрыть его - например, обернув его внутри одного только с первым параметром – Carsten
Этот [пакет ] (https://hackage.haskell.org/package/memoize-0.7/docs/Data-Function-Memoize.html), вероятно, вас интересует. Эта библиотека предоставляет вам функцию memoFix :: Memoizable a => ((a -> v) -> a -> v) -> a -> v', которая будет меморировать функцию одного аргумента, написанную в открытой рекурсивной форме. Обратите внимание, что он вообще не заботится о его возвращаемом типе, т. Е. 'V' может быть самой функцией. – user2407038
Но эта функция, которую он возвращает, будет оцениваться каждый раз, когда параметр передается ей снова, не так ли? –