На самом деле, вопреки взаимопониманию Монад, они не имеют никакого отношения к состоянию. Монады являются просто путем к переносящимся вещам и предоставляют методы, чтобы сделать операции на обернутом материале, не разворачивая его.
, Например, можно создать тип для обертывания другого в Haskell:
data Wrapped a = Wrap a
Для обертывания материала мы определяем
return :: a -> Wrapped a
return x = Wrap x
, Чтобы выполнить операции без разворачивания, сказать, что у Вас есть функция f :: a -> b
, тогда можно сделать это к [1 115] лифт что функция для действия на обернутые значения:
fmap :: (a -> b) -> (Wrapped a -> Wrapped b)
fmap f (Wrap x) = Wrap (f x)
Это обо всех, там должен понять. Однако оказывается, что существует более общая функция, чтобы сделать этот подъем , который является bind
:
bind :: (a -> Wrapped b) -> (Wrapped a -> Wrapped b)
bind f (Wrap x) = f x
bind
может сделать [больше чем 117], но не наоборот. На самом деле, fmap
может быть определен только с точки зрения bind
и return
. Так, при определении монады.. Вы даете его тип (здесь, это было Wrapped a
), и затем скажите, как его return
и bind
операции работают.
прохладная вещь состоит в том, что это оказывается таким общим шаблоном, что он открывается повсеместно, инкапсулирование состояния чистым способом является только одним из них.
Для хорошей статьи о то, как монады могут использоваться, чтобы представить функциональные зависимости и таким образом управлять порядком оценки, как он, используется в монаде Haskell IO, проверьте IO В .
Что касается понимания монад, не волнуйтесь слишком много об этом. Считайте о них, что Вы находите интересными и не волнуете, не понимаете ли Вы сразу же. Тогда просто дайвинг на языке как Haskell является способом пойти. Монады являются одной из этих вещей, где, понимая струйки в Ваш мозг практикой, однажды Вы просто внезапно понимаете понимание их.
Я наконец извлек тестовый набор из более чем 200 примеров дат, которые действительно встречаются в наборе данных. Некоторые плохо себя ведут, некоторые совсем больны (например, «01010»).
Я перепробовал все существующие модули Perl, которые смог найти, но вероятность успеха была слишком низкой. В конце концов я заново изобрел свое колесо, добившись более 98% успеха.
Мой алгоритм представляет собой последовательность все более нечетких распознавателей, начиная с жестко действительных дат до общей территории предположений. Побеждает тот, кто первым вернет результат "успех". В середине этого стека у меня есть «главный» распознаватель, который делает что-то вроде этого:
анализирует наборы чисел в строке в любом месте. Также распознаются «названия месяцев» на французском и английском языках.
Для каждого из них я разделил их на три корзины: кандидаты на год, кандидаты на месяц, кандидаты на день. Например, «13» будет в сегменте «возможный год» и в сегменте «возможный день». «Февраль», конечно, уйдет только в «месячное» ведро. В каждом сегменте значение помечено «уровнем правдоподобия» - произвольным числом, которое зависит от ряда вещей. Например, 2010 год более правдоподобен, чем год 10.
посмотрите в каждую из трех корзин. Если в каком-либо из них есть только один элемент, это значение для этого сегмента. Он также удален из других ведер.
ищут оставшиеся пропущенные значения в соответствующих сегментах по порядку (год, месяц, день), выбирая наиболее правдоподобное. В случае ничьей возьмите тот, который встречается последним в строке (на самом деле, у них немного больше правдоподобия).Эти правила нарушают 7/3/2010 как 7 марта, как мне нужно здесь, во Франции. Удалите это значение из других сегментов, если это применимо.
если какое-либо значение отсутствует, используйте значение по умолчанию (например, я использую 8191 как год по умолчанию, самое большое допустимое значение в моей целевой системе).
Все это ужасно эвристика, но соответствует моему требованию, что лучше иметь мусор, чем терять информацию.
Date :: Manip - ваш друг, так как он терпит неудачу только в одном из четырех, потому что он принимает формат США, используя Date_Init, вы можете получить 4 из 4.
Если у вас есть разные форматы (например, месяц до дня и наоборот), вам придется анализировать их по-разному, один раз с форматом даты в США, а следующий с форматом даты, отличным от американского. Это особенно важно, когда он неоднозначен, как ваш пример 3/4/97, потому что, если он 21/3, он просто не работает, и вы можете сказать, что формат неправильный.
vinko@mithril:~$ more date.pl
use strict;
use warnings;
use Date::Manip;
my @a;
push @a, "March 2004";
push @a, "2001";
push @a, "3/4/97";
push @a, "21/3/1998";
Date_Init("DateFormat=non-US");
for my $d (@a) {
print "$d\n";
print ParseDate($d)."\n";
};
vinko@mithril:~$ perl date.pl
March 2004
2004030100:00:00
2001
2001010100:00:00
3/4/97
1997040300:00:00
21/3/1998
1998032100:00:00
Вы также можете взглянуть на DateTime :: Format :: Flexible
Судя по его описанию, он вам подойдет:
Если вам когда-либо приходилось использовать программу что заставило вас ввести дату определенным образом и подумал: "Почему не может компьютер просто выяснил, какого числа я хотел? ", этот модуль для вас.
DateTime :: Format :: Гибкие попытки возьмите любую строку, которую вы ей даете, и проанализируйте в объект DateTime.
Я только что запустил версию сценария Vinko, используя этот модуль, и получил аналогичные результаты. Все нормально, кроме последнего случая (21.03.1998). Как и в случае с Date :: Manip
, вы можете относительно легко справиться с этим, явно задав параметр ( european => 1
). Комментарий Данбистрома показывает, почему такие дела нуждаются в надзоре со стороны человека.
Это не Perl, но эта библиотека .NET будет анализировать широкий диапазон строк даты и времени.