Извлечь данные из сигнала

У меня есть такой сигнал: signal1 = Signal.constant {a=4, b=3, l = []}
Как извлечь данные из сигнала?
я пытался Signal.map (\x -> x) signal1 но Signal.map возвращает другой сигнал.

2 ответа

Если во время программирования в Elm у вас когда-нибудь возникнут вопросы

  • "Как извлечь значение из сигнала?"
  • "Как мне изменить эту переменную на другое значение?"
  • "Куда я положу foldp и какие аргументы я должен передать в это?

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

Тем не менее, я приведу упрощенное резюме - имейте в виду, что я опускаю много деталей и сложностей. Если вы читали учебник, вы, вероятно, понимаете, как устроена типичная программа Elm. В большинстве программ Elm есть 3 основные части: модель, обновление и просмотр.

Модель содержит начальные значения для всех данных вашей программы и определения их типов. Обновление принимает событие и модель и возвращает измененную модель на основе события. View берет модель (на каком бы этапе программа в данный момент не находилась) и рисует ее на экране, другими словами, возвращает Element,

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

import Graphics.Element exposing (Element, show)
import Mouse
import Signal exposing (Signal, map)

main : Signal Element
main = map show Mouse.isDown

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

main = map view (foldp update model signal)

main функция всегда имеет тип Signal Element - есть исключения, но за кадром они преобразуются в Signal Element тем не мение. Что бы вы ни делали со своими данными, кодом и функциями, в какой-то момент вы должны объединить все это во что-то типа Signal Element, который будет телом вашего main функция.

Модель, как правило, представляет собой запись со многими полями, любое из которых также может быть записью. Обновление обычно имеет тип Event -> Model -> Model, где Model это тип вашей модели и Event что бы ни испускал ваш последний сигнал. Вид обычно имеет тип Model -> Element, (Имена типов не должны быть Event а также Model Я использую их в качестве заполнителей в этом примере).

Вы не можете извлечь значения из Сигнала, это намеренно невозможно в Elm. Вместо этого вы поднимаете функцию в Signal контекст, используя Signal.map, Все манипуляции со значениями, испускаемыми сигналом, выполняются в течение Signal контекст с помощью функций, которые подняты в него. Предположим, у вас есть signal типа Signal Event, затем foldp update model signal будет иметь тип Signal Model, так как foldp имеет тип:

foldp : (a -> state -> state) -> state -> Signal a -> Signal state

Если ваша функция просмотра имеет тип Model -> Element, затем map view (foldp update model signal) будет иметь тип Signal Element,

main уполномочен иметь тип Signal Element, следовательно map view (foldp update model signal) может быть телом main,

import Graphics.Element exposing (Element, show)
import Mouse
import Signal exposing (Signal, foldp, map)

type alias Model = Int
model : Model
model = 0

update : () -> Model -> Model
update event model = model + 1

view : Model -> Element
view model = show model

main : Signal Element
main = map view (foldp update model Mouse.clicks)

Выше очень простая программа, которая накапливает щелчки мыши. У нас есть фиктивное событие, а наша модель - просто целое число. Как Signal.map функция работы? Имеет тип:

map : (a -> b) -> Signal a -> Signal b

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

Потому что вы должны иметь main функция, в какой-то момент вам придется преобразовать ваш окончательный сигнал в Signal Element, так что в какой-то момент вам придется сопоставить (поднять) функцию типа Something -> Element над Signal Something получить Signal Element, Почему это называется лифтинг? Из-за частичного применения эти 2 определения типа Signal.map эквивалентны:

map : (a -> b) -> Signal a -> Signal b
map : (a -> b) -> (Signal a -> Signal b)

Вы поднимаете обычную повседневную функцию типа a -> b в Signal контекст, так что он может работать на сигналах значений, а не только значения. Вот более сложный пример, который считает и секунды, и щелчки мыши:

import Graphics.Element exposing (Element, show)
import Mouse
import Signal exposing (Signal, foldp, map, merge)
import Time exposing (Time, fps, inSeconds)

type alias Model = { clicks : Int, time : Int }
model : Model
model = { clicks=0, time=0 }

type Event = Seconds Int | Mouse ()
update : Event -> Model -> Model
update event model = case event of
  Seconds time -> { model | time <- model.time + time }
  Mouse () -> { model | clicks <- model.clicks + 1 }

view : Model -> Element
view model = show model

timeSignal = Seconds << round << inSeconds <~ fps 1
mouseSignal = map Mouse Mouse.clicks

signal : Signal Event
signal = merge timeSignal mouseSignal

main : Signal Element
main = map view (foldp update model signal)

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

Это намеренно почти невозможно, потому что вам это не нужно.

Зачем? Ну, это может помочь посмотреть на одну из возможных сигнатур main в приложении Elm:

main : Signal Element

Здесь мы заявляем, что тип нашей программы является Сигналом Элемента; это означает, что наша программа является элементом, который изменяется со временем. Среда исполнения Elm будет определять для нас бит "изменения во времени", при условии, что мы дадим ему знать, какие сигналы нам нужны (путем ссылки на них) и как их соединить (используя map, foldp и т. Д.),

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

Если вы просто хотите посмотреть значение во время выполнения (например, в журнале консоли), взгляните на:

http://package.elm-lang.org/packages/elm-lang/core/2.1.0/Debug

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