Как Вы комбинируете условия фильтра

Вы можете передавать данные в ответ, но вы не можете динамически обновлять шаблон так, как вы описываете. Шаблон создается один раз на стороне сервера, а затем отправляется клиенту. Вам нужно будет использовать JavaScript для чтения потокового ответа и вывода данных на стороне клиента.

Используйте XMLHttpRequest, чтобы сделать запрос к конечной точке, которая будет передавать данные. Затем периодически читайте поток, пока он не будет выполнен.

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

from time import sleep
from flask import Flask, render_template
from math import sqrt

app = Flask(__name__)

@app.route('/')
def index():
    # render the template (below) that will use JavaScript to read the stream
    return render_template('index.html')

@app.route('/stream_sqrt')
def stream():
    def generate():
        for i in range(500):
            yield '{}\n'.format(sqrt(i))
            sleep(1)

    return app.response_class(generate(), mimetype='text/plain')

app.run()
<p>This is the latest output: <span id="latest"></span></p>
<p>This is all the output:</p>
<ul id="output"></ul>
<script>
    var latest = document.getElementById('latest');
    var output = document.getElementById('output');

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '{{ url_for('stream') }}');
    xhr.send();
    var position = 0;

    function handleNewData() {
        // the response text include the entire response so far
        // split the messages, then take the messages that haven't been handled yet
        // position tracks how many messages have been handled
        // messages end with a newline, so split will always show one extra empty message at the end
        var messages = xhr.responseText.split('\n');
        messages.slice(position, -1).forEach(function(value) {
            latest.textContent = value;  // update the latest value in place
            // build and append a new item to a list to log all output
            var item = document.createElement('li');
            item.textContent = value;
            output.appendChild(item);
        });
        position = messages.length - 1;
    }

    var timer;
    timer = setInterval(function() {
        // check the response for new data
        handleNewData();
        // stop checking once the response has ended
        if (xhr.readyState == XMLHttpRequest.DONE) {
            clearInterval(timer);
            latest.textContent = 'Done';
        }
    }, 1000);
</script>
24
задан 9 May 2009 в 00:09
поделиться

3 ответа

Комбинатор liftM2 можно использовать в монаде Reader, чтобы сделать это «более функциональным» способом:

import Control.Monad
import Control.Monad.Reader

-- ....

filter (liftM2 (&&) odd (> 100)) [1..200]

Обратите внимание, что импорт важен; Control.Monad.Reader предоставляет экземпляр Monad (e ->), который заставляет все это работать.

Причина, по которой это работает, в том, что монада читателя просто (e ->) для некоторой среды e. Таким образом, логический предикат является 0-арной монадической функцией, возвращающей bool в среде, соответствующей его аргументу. Затем мы можем использовать liftM2 для распределения среды по двум таким предикатам.

Или, проще говоря, liftM2 будет действовать примерно так, когда типы работают:

liftM2 f g h a = f (g a) (h a)

Вы также можете определить новый комбинатор, если хотите иметь возможность их легко связать, и / или не хотите связываться с liftM2:

(.&&.) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(.&&.) f g a = (f a) && (g a)
-- or, in points-free style:
(.&&.) = liftM2 (&&)    

filter (odd .&&. (> 5) .&&. (< 20)) [1..100]
31
ответ дан bdonlan 28 November 2019 в 22:43
поделиться

Допустим, ваши условия хранятся в списке под названием conditions. Этот список имеет тип [a -> Bool].

Чтобы применить все условия к значению x, вы можете использовать map:

map ($ x) conditions

Это применяет каждое условие к x и возвращает список Bool. Чтобы свести этот список к одному логическому значению: True, если все элементы имеют значение True, и False в противном случае, вы можете использовать функцию and:

and $ map ($ x) conditions

Теперь у вас есть функция, которая объединяет все условия. Давайте дадим ему имя:

combined_condition x = and $ map ($ x) conditions

Эта функция имеет тип a -> Bool, поэтому мы можем использовать ее при вызове filter:

filter combined_condition [1..10]
11
ответ дан Ayman Hourieh 28 November 2019 в 22:43
поделиться

Well, you can combine functions however you want in Haskell (as long as the types are correct) and using lambdas you don't even have to name your predicate function, i.e.,

filter (\x -> odd x && x > 100) [1..200]
16
ответ дан 28 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

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