Идиоматический способ последовательности действий с эффектами в Haskell [duplicate]

Обновление летом 2017:

См. http://caniuse.com/#search=modules , новая поддержка, возможно, потребуется изменить настройки.

] Теперь, когда вещи менее расплывчаты. Чтобы сделать работу модуля, вы должны сообщить браузеру, что это модуль (другой - скрипт). Первый путь неявный, импортированный модуль всегда является модулем. Второй способ - с модулем типа

Убедитесь, что импорт и экспорт находятся только на верхнем уровне, а не внутри блока, а не внутри оператора if, а не внутри цикла и т. Д.

Также обязательно укажите полный путь (включая .js), он должен начинаться с ./ или ../.

Устаревший ответ ниже:

Устаревший ответ: [f9]

eval в строке модуля не будет работать. Синтаксис импорта и экспорта модуля ES2015 не поддерживается ни одним браузером в момент написания этого ответа (04/2016). Сообщение об ошибке пропущено, потому что это означает, что синтаксис поддерживается, но он вообще не поддерживается. См. Первую заметку здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Причина в том, что спецификация для модульных погрузчиков все еще продолжается работа. См. https://whatwg.github.io/loader/#status

. Они являются инструментами, однако, для полировки или для автоматического преобразования этого синтаксиса как babel.

4
задан WalterM 8 October 2015 в 03:21
поделиться

3 ответа

Во многих случаях эти глубоко вложенные углубления являются результатом глубоко вложенной проверки ошибок. Если это так, вы должны изучить MaybeT и его старшего брата ExceptT. Они предлагают чистый способ отделить код «что мы делаем, когда что-то пошло не так» от кода «что мы делаем, если все идет правильно». В вашем примере я могу написать:

data CustomError = IfCheckFailed | MaybeCheckFailed

main = handleErrors <=< runExceptT $ do
    inFH  <- liftIO $ openFile ...
    outFH <- liftIO $ openFile ...
    forM myList $ \item -> do
        when (...) (throwError IfCheckFailed)
        ...
        x <- liftMaybe MaybeCheckFailed ...
        ...

liftMaybe :: MonadError e m => e -> Maybe a -> m a
liftMaybe err = maybe (throwError err) return

handleErrors :: Either CustomError a -> IO a
handleErrors (Left err) = case err of
    IfCheckFailed    -> ...
    MaybeCheckFailed -> ...
handleErrors (Right success) = return success

Обратите внимание, что мы все еще увеличиваем отступ в цикле forM; но другие проверки выполняются «in-line» в main и обрабатываются на одном уровне отступов в handleErrors.

9
ответ дан Daniel Wagner 22 August 2018 в 20:58
поделиться

Вы должны сделать то же самое, что и с другим языком программирования. Функции должны быть понятны. Обычно это означает, что если он длинный, поток управления невелик, в противном случае он разделяется на отдельные функции.

Таким образом, главное может выглядеть так:

main = do
    inFH <- openFile ...
    outFH <- openFile ....

    mapM prcoessItem myList
2
ответ дан dave 22 August 2018 в 20:58
поделиться
  • 1
    Эм, это в значительной степени несовместимо с заявленным требованием не пропускать inFH и outFH всюду. – Ørjan Johansen 8 October 2015 в 17:56

Хотя вероятнее всего есть более эффективные способы решения вашей конкретной проблемы (см., например, ответ Дэниела Вагнера), вы всегда можете использовать let для ввода нового имени в произвольной области. Вот, по общему признанию, бессмысленная демонстрация:

main = do
    inFH <- return "inf"
    outFH <- return "ouf"

    let subAction = do
            if length inFH > 2
                then print "foo"
                else subSubAction

        subSubAction = case outFH of
            [] -> print "bar"
            _ -> print "baz"

    forM [1..10] $ \ item -> do
        print item
        subAction
5
ответ дан duplode 22 August 2018 в 20:58
поделиться
  • 1
    Благодарю. Это то, что я переглядывал. Однако, одна вещь, которую мне не нравится в использовании let, заключается в том, что она меняет порядок чтения - я сначала определяю часть шага, а затем приходит остальная часть потока. Мне также не нравится включать часть логического потока в имя, что является еще одной причиной, по которой я не хотел использовать where. – trVoldemort 8 October 2015 в 21:58
Другие вопросы по тегам:

Похожие вопросы: