Не удается прочитать свойство 'kids' из undefined - или как нарушить циклическую зависимость сигналов в Elm?

В то время как elm-make успешно, я получаю следующую ошибку в браузере:

Невозможно прочитать свойство "дети" из неопределенного

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

model -> clicks -> model

Вот соответствующий код:

model : Signal Model
model =
  Signal.foldp update initialModel clicks


clicks : Signal Action
clicks =
  let
    clickPosition = Mouse.position
      |> Signal.sampleOn Mouse.clicks
    tuplesSignal = Signal.map3 (,,) clickPosition Window.dimensions model      
  in
    ...

Похоже на model В Эльме это общепринятая практика, поэтому я должен clicks -> model зависимость.

Вот некоторый контекст:

Я строю скользящую головоломку, используя холст:

Когда пользователь щелкает плитку, которая может двигаться, она должна двигаться. В противном случае щелчок следует игнорировать.

clicks произведет следующие действия: Left, Right, Up, Down

Например, если пользователь нажимает на плитки 12, 11, 8, 15 (в этом порядке), clicks должно быть: Down -> Right -> Up

Проблема в том, что для того, чтобы вычислить, на какой плитке был нажат, мне нужно знать размеры доски (например, 4 строки и 4 столбца на рисунке выше). Но размеры платы хранятся в model (представьте пользовательский интерфейс, который позволяет пользователям изменять размеры платы).

Как мне выйти из этой круговой зависимости?

1 ответ

Решение

В этом случае я думаю, что вы должны перейти на более низкий уровень в том, что вы называете входом, и принять позиции нажатия в качестве входных данных. Тогда вы можете составить update функция в вашем Signal.foldp из двух других:

  1. Первый превращает клики и модель в Maybe Direction (при условии Left, Right, Up, Down являются конструкторами типа Direction)
  2. Вторая функция, которая принимает Direction стоимость и модель для расчета новой модели. Ты можешь использовать Maybe.map а также Maybe.withDefault обращаться с Maybe часть результата первой функции.

Разделение этих двух частей, даже если вы производите и потребляете Direction немедленно, делает вашу систему более самодокументированной и показывает концептуальное разделение между необработанным вводом и ограниченным "фактическим" вводом.

PS Есть мыслимые расширения языка Elm, которые позволили бы вам легче написать эту предварительную обработку ввода в сигнальной земле. Но такие расширения сделают сигнальную часть языка настолько мощной, что неясно, сделает ли это "правильный путь" структурирования программ более трудным для обнаружения.

Другие вопросы по тегам