insertionPCost
, deletionPCost
, substitutionPCost
и substitutionCostIfNEQ
вызываются только друг от друга и cost
, и всегда с одинаковыми аргументами (за исключением того, что substitutionCostIfNEQ
не принимает m
);так что мы можем переставить их следующим образом:
cost = \m -> \s1 -> \s2 -> minimum [insertionPCost, deletionPCost, substitutionPCost]
where insertionPCost = m Map.! (s1, init s2) + 1
deletionPCost = m Map.! (init s1, s2) + 1
substitutionPCost = m Map.! (init s1, init s2) + substitutionCostIfNEQ
substitutionCostIfNEQ = if (last s1 == last s2) then 0 else 2
И явные лямбды ничего вам не дают, поэтому перепишите, чтобы было яснее:
cost m s1 s2 = minimum [insertionPCost, deletionPCost, substitutionPCost]
where insertionPCost = m Map.! (s1, init s2) + 1
deletionPCost = m Map.! (init s1, s2) + 1
substitutionPCost = m Map.! (init s1, init s2) + substitutionCostIfNEQ
substitutionCostIfNEQ = if (last s1 == last s2) then 0 else 2
Чтобы ответить на ваш второйвопрос, в настоящее время у вас есть
editDistance :: Distances -> (String,String) -> Distances
Если бы вы использовали вместо него State
, это было бы
editDistance :: (String,String) -> State Distances ()
То есть editDistance
была бы функцией, которая принимает (String,String)
и дает что-то, что взаимодействует с состоянием Distances
, и не имеет никакого другого значимого результата.
Но.
Во-первых, я не вижу, что с вашим использованием * есть что-то не так foldl
.
Во-вторых, вы никогда не используете накопленное значение, каким бы оно ни было.Вы используете это, чтобы создать новое значение, но вы ничего не ищите в нем.Таким образом, вам не нужно State
, вам нужно только Writer
.
editDistance :: (String,String) -> Writer Distances ()
То есть editDistance
будет функцией, которая принимает (String,String)
и дает что-то, что добавляет к Distances
аккумулятор, и никакого другого значимого результата.
(Здесь есть одна тонкость: первый параметр Writer
должен быть Monoid
, и он должен использовать операцию объединения (mappend
)это полезно для вас, ну, Map
s это Monoid
s, и их mappend
- это то же самое union
, которое вы используете в своем оригинальном editDistance
, так что все работает нормально. *