Использование Haskell указывает монаде запах кода?

Сейчас это не поддерживается. Flutter Studio не выглядит стабильно и содержит ошибки. Таким образом, до сих пор единственным предпочтительным способом является использование Hot Reload . Если вы хотите отладить проблемы, связанные с макетом, вы можете сделать следующее:

  1. импортировать это в корневой файл (например, main.dart)

import 'package:flutter/rendering.dart'; [1114 ]

  1. в вашей функции main(), добавьте эти строки, чтобы включить отладку макета перед методом runApp():

debugPaintSizeEnabled = true;

debugPaintBaselinesEnabled = true; [1116 ]

debugPaintPointersEnabled = true;

57
задан Don Stewart 17 April 2011 в 21:01
поделиться

7 ответов

Я бы сказал, что состояние в целом не является запахом кода, если оно остается небольшим и хорошо контролируется.

Это означает, что использование таких монад, как State, ST или созданные на заказ, или просто наличие структуры данных, содержащей данные о состоянии, которые вы передаете в несколько мест, - это неплохо. (На самом деле, монады просто помогают в этом!) Однако наличие состояния, которое распространяется повсюду (да, это означает, что вы, монада ввода-вывода!) - неприятный запах.

Достаточно наглядным примером этого является то, что моя команда работала над нашей записью на ICFP Programming Contest 2009 (код доступен на git : //git.cynic.net/haskell/icfp-contest-2009). В итоге мы получили несколько различных модульных частей:

  • ВМ: виртуальная машина, на которой выполнялась программа моделирования
  • Контроллеры: несколько различных наборов процедур, которые считывают выходные данные симулятора и генерируют новые управляющие входы
  • Решение : создание файла решения на основе выходных данных контроллеров
  • Визуализаторы: несколько различных наборов процедур, которые считывают как входные, так и выходные порты и генерируют своего рода визуализацию или журнал того, что происходило, по мере продвижения моделирования

Каждый из них имеет собственное состояние, и все они по-разному взаимодействуют через входные и выходные значения виртуальной машины. У нас было несколько разных контроллеров и визуализаторов, каждый из которых имел свой собственный тип состояния.

Ключевым моментом здесь было то, что внутренние компоненты любого конкретного состояния были ограничены своими собственными конкретными модулями, и каждый модуль ничего не знал даже о наличие состояния для других модулей. Любой конкретный набор кода и данных с отслеживанием состояния обычно состоял из нескольких десятков строк с несколькими элементами данных в состоянии.

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

Когда состояние используется таким ограниченным образом, а система типов не дает вам случайно изменить его, с этим довольно легко справиться. Одно из преимуществ Haskell - то, что он позволяет вам это делать.

Один из ответов гласит: «Не используйте монады». С моей точки зрения, это как раз наоборот. Монады - это управляющая структура, которая, помимо прочего, может помочь вам минимизировать объем кода, который касается состояния. Если вы посмотрите на монадические синтаксические анализаторы в качестве примера, состояние синтаксического анализа (т. Е. Анализируемый текст, расстояние до него, любые накопленные предупреждения и т. Д.) Должно проходить через каждый комбинатор, используемый в синтаксическом анализаторе. . Тем не менее, будет только несколько комбинаторов, которые непосредственно управляют состоянием; все остальное использует одну из этих немногих функций.

42
ответ дан 24 November 2019 в 19:43
поделиться

Я записал несколько компиляторов в Haskell, и монада состояния является разумным решением многих проблем компилятора. Но Вы хотите сохранить это, краткий обзор---не делает это очевидным, что Вы используете монаду.

Вот пример из Компилятора Haskell Глазго (который я сделал не запись; я просто работаю вокруг нескольких краев), где мы создаем графики потока управления. Вот основные способы сделать графики:

empyGraph    :: Graph
mkLabel      :: Label -> Graph
mkAssignment :: Assignment -> Graph  -- modify a register or memory
mkTransfer   :: ControlTransfer -> Graph   -- any control transfer
(<*>)        :: Graph -> Graph -> Graph

, Но поскольку Вы обнаружили, поддержав предоставление уникальных маркировок, утомительно в лучшем случае таким образом, мы обеспечиваем эти функции также:

withFreshLabel :: (Label -> Graph) -> Graph
mkIfThenElse :: (Label -> Label -> Graph) -- branch condition
             -> Graph   -- code in the 'then' branch
             -> Graph   -- code in the 'else' branch 
             -> Graph   -- resulting if-then-else construct

целое Graph вещью является абстрактный тип, и переводчик просто весело создает графики чисто функциональным способом, не будучи знающим, что что-либо одноместное продолжается. Затем когда график наконец создается для превращения его в алгебраический тип данных, от которого мы можем сгенерировать код, мы даем ему предоставление уникальных маркировок, выполняем монаду состояния и вытаскиваем структуру данных.

монада состояния скрыта внизу; хотя это не представлено клиенту, определение Graph является чем-то вроде этого:

type Graph = RealGraph -> [Label] -> (RealGraph, [Label])

или немного более точно

type Graph = RealGraph -> State [Label] RealGraph
  -- a Graph is a monadic function from a successor RealGraph to a new RealGraph

С монадой состояния, скрытой позади слоя абстракции, это не является вонючим вообще!

44
ответ дан Norman Ramsey 24 November 2019 в 19:43
поделиться

Вы посмотрели Атрибутные грамматики (AG)? (Больше информации о Википедия и статья в Читателе Монады)?

С AG можно добавить атрибуты к синтаксическому дереву. Эти атрибуты разделяются в , синтезировал , и наследовался атрибуты.

Синтезируемые атрибуты являются вещами, которые Вы генерируете (или синтезируйте) от Вашего синтаксического дерева это могло быть сгенерированным кодом или всеми комментариями, или безотносительно Вашего заинтересованного.

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

В Утрехтском университете мы используем Система Атрибутной грамматики ( UUAGC) для записи компиляторов. Это - препроцессор, который генерирует haskell код (.hs файлы) от обеспеченного .ag файлы.

<час>

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

В этом случае, Вы могли вручную записать вид кода, который грамматики атрибутов генерируют для Вас, например:

data AbstractSyntax = Literal Int | Block AbstractSyntax
                    | Comment String AbstractSyntax

compile :: AbstractSyntax -> [Label] -> (Code, Comments)
compile (Literal x) _      = (generateCode x, [])
compile (Block ast) (l:ls) = let (code', comments) = compile ast ls
                             in (labelCode l code', comments)
compile (Comment s ast) ls = let (code, comments') = compile ast ls
                             in (code, s : comments')

generateCode :: Int -> Code
labelCode :: Label -> Code -> Code
6
ответ дан Tom Lokhorst 24 November 2019 в 19:43
поделиться

Возможно, что можно хотеть применимый функтор вместо монады:

http://www.haskell.org/haskellwiki/Applicative_functor

я думаю, что исходная бумага объясняет это лучше, чем Wiki, однако:

http://www.soi.city.ac.uk/~ross/papers/Applicative.html

3
ответ дан jrockway 24 November 2019 в 19:43
поделиться

В целом необходимо стараться избегать состояния по мере возможности, но это не всегда практично. Applicative заставляет код effectful выглядеть более хорошим, и более функциональный код особенно обхода дерева может извлечь выгоду из этого стиля. Для проблемы поколения имени существует теперь довольно хороший доступный пакет: предоставление значения .

0
ответ дан nominolo 24 November 2019 в 19:43
поделиться

Ну, не используйте монады. Питание функционального программирования является функциональной чистотой и их повторным использованием. Существует данная статья, которую однажды записал мой преподаватель, и он - один из парней, которые помогли создать Haskell.

бумагу называют" , Почему функциональное программирование имеет значение ", я предполагаю, что Вы прочитываете его. Это - хорошее чтение.

-5
ответ дан John Leidegren 24 November 2019 в 19:43
поделиться

давайте будем осторожны относительно терминологии здесь. Состояние не по сути плохо; функциональные языки имеют состояние. То, что является "запахом кода", когда Вы желаете, чтобы присвоить значения переменных и изменить их.

, Конечно, монада состояния Haskell там для просто, что причина - как с вводом-выводом, она позволяет Вам сделать небезопасные и нефункциональные вещи в ограниченном контексте.

Так, да, это - вероятно, запах кода.

-13
ответ дан Charlie Martin 24 November 2019 в 19:43
поделиться
Другие вопросы по тегам:

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