Совершенно новичок в Haskell, и я был бы признателен за помощь.
Реализация предикатов на Прологе, которые используют некоторые ограничения, сокращающие пространство решения, так что общая реализация не является наивной/грубой, чрезвычайно проста. Однако теперь, когда мне приходится иметь дело с Haskell, я понятия не имею, как это сделать.
Учитывая, что в какой-то момент P1 я делаю выбор, скажем, A1, а в более поздний момент времени P2 я делаю выбор, скажем, A2, который не подчиняется моему ограничению, как я могу вернуться к P1 и сделать другой выбор в Haskell?
Я изучаю Haskell уже 2 дня, и из того, что я прочитал, это может быть выполнимо либо путем объявления функции внутри функции, либо с использованием монад, которые я действительно не понимаю и смущаю меня.
Не могли бы вы связать меня с / показать мне несколько простых предикатов Pick it — оставить его под ограничениями, которые используют возврат с возвратом — желательно без монад — чтобы я мог обдумать это?
@MichaelLitchard Отредактировал вопрос, чтобы он более точно отражал то, что мне нужно.
Конечно, вот простой, который выбирает число, а затем, если обнаруживает, что число нечетное, он делает резервную копию и выбирает другое.
searchForEven :: [Int] -> [Int]
searchForEven ns = [n | n <- ns, even n]
Вот пример, который соответствует описанной вами ситуации:
Учитывая, что в какой-то момент P1 я делаю выбор, скажем, A1, а в более поздний момент времени P2 я делаю выбор, скажем, A2, который не подчиняется моему ограничению, как я могу вернуться к P1 и сделать другой выбор?
p1 = [1..10]
p2 = [2,3,5,7]
constraint a b = a^2 + b^2 == 5^2
searchForPythagoreanTriple :: [Int]
searchForPythagoreanTriple =
[ (a1, a2)
| a1 <- p1
, a2 <- p2
, constraint a1 a2
]
Я использовал имена, которые, как я надеюсь, достаточно наводящие на размышления, чтобы подчеркнуть, как пример связан с описанным вами сценарием.
И не бойтесь монады. Посмотрите, насколько он идентичен синтаксису монад:
searchForEven ns = do
n <- ns
guard (even n)
pure n
searchForPythagoreanTriple = do
a1 <- p1
a2 <- p2
guard (constraint a1 a2)
pure (a1, a2)
Таким образом, принцип работы Guard заключается в том, что он следит за тем, чтобы ограничение не было нарушено? Что, если бы у меня было несколько ограничений?
@RookieCookie Да, для списков, guard False = []; guard True = [()]
. Если бы у вас было несколько ограничений, у вас было бы несколько вызовов guard
.
@MichaelLitchard Вопрос больше о возврате в Haskell в целом.