let loop = loop in if loop then Just 1 else Nothing имеет тип Maybe Int, но это ни Just, ни Nothing. Чтобы различить их, вызывающему нужно условие, а условие так и не выдаёт значение Bool. Внешнего конструктора, который можно было бы осмотреть, нет.
Just loop с тем же loop = loop ведёт себя иначе. Внешний Just можно осмотреть, расходится только требование вложенного целого. Важно, чего именно требует вызывающий. Упоминание Maybe в типе не делает ни одно из выражений тотальным.
Различие становится практическим, когда вычислитель умеет останавливаться по исчерпании бюджета шагов. Что должна сообщить обёртка, когда бюджет кончился, NotFound или собственный результат Unfinished?
Я выбираю Unfinished. NotFound подходит для завершённого поиска, который по своим правилам показал отсутствие. Исчерпанный бюджет значит лишь, что это вычисление не закончилось. Он ничего не доказывает ни об отсутствии решения, ни о том, нашлось бы оно за большее число шагов.
Отдельный случай оправдан, если вызывающие могут продолжить поиск, изменить бюджет или объяснить неопределённость. Если обе ветки используются одинаково, различие мало что даёт. Maybe описывает отсутствие и наличие, когда вычисление доходит до конструктора, а дно (bottom) остаётся возможным.