2014-01-02 6 views
3

Есть ли способ иметь Behavior t [a], где значения [a] в момент времени t являются значениями, содержащимися в Behavior t [Behavior t a] в момент времени t? То есть, функция с типом:Возможно ли: поведение t [Поведение t a] -> Поведение t [a]

Behavior t [Behavior t a] -> Behavior t [a] 

Если это не возможно, является то, что из-за логической невозможности или ограничения в реакционно-банан?

+0

Подпись типа действительна, можете ли вы объяснить, что конкретно представляет собой ваша проблема? Если я правильно понял, вы хотите сделать какую-то фильтрацию? – Adrian

+3

Я не знаю реактивно-банановых, но есть еще вопрос о том, заселен ли этот тип. –

+0

Спасибо, что упомянул, что «тип обитаемый», он приводит меня к вики-странице теоремы об изоморфизме Карри-Говарда на Haskell Wiki. – Adrian

ответ

12

Тип тривиальным заселена для любого Applicative:

{-# LANGUAGE RankNTypes #-} 
import Control.Applicative 
import Control.Monad 
import Data.Functor.Identity 
import qualified Data.Traversable as T 

f' :: (Applicative f) => f [f a] -> f [a] 
f' = const $ pure [] 

, который явно не то, что вы хотели. Так давайте спросим для обитания

(Traversable t) => Behavior u (t (Behavior u a)) -> Behavior u (t a) 

или в более общем плане, для которых аппликативных мы можем построить

(T.Traversable t) => f (t (f a)) -> f (t a) 

Это заселена для любого f, который также является монадой:

f :: (Monad m, T.Traversable t) => m (t (m a)) -> m (t a) 
f = join . liftM T.sequence 

Очевидным возникает вопрос: если аппликатив имеет такой f, то он должен быть монадой? Ответ есть. Мы просто применить f к Identity проходимой (коллекции один-элемент - Traversable экземпляр Identity) и построить join в

g :: (Applicative m) => (forall t . (T.Traversable t) => m (t (m a)) -> m (t a)) 
        -> (m (m a) -> m a) 
g f = fmap runIdentity . f . fmap Identity 

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

В заключение: Функция, которую вы ищете, будет существовать тогда и только тогда, когда Behavior были Monad. И поскольку это не так, скорее всего, такой функции нет. (Я считаю, что если бы существовал способ, как сделать это монада, было бы включить в библиотеку.)

+1

Я был почти вынужден этой идеей, но потом я увидел, что модель, продемонстрированная в моем комментарии, должна быть возможной нетривиальной функцией для любого Functor. Это, очевидно, все еще подразумевает Monad, поэтому я думаю, мне любопытно, почему модель является монадой, но реализация не является. –

+0

@ J.Abrahamson Думаю, причина в том, что модель 'Time -> a' позволяет нам получить доступ к любому значению в произвольное время. Но в реализации FRP это невозможно, мы можем получить доступ к «сейчас» или что-то еще. Я не уверен, но это может быть причиной. –

+0

@ PetrPudlák: в типе 'Reader' можно определить монадическое' join', используя экземпляр 'Applicative':' join ra = runReader <$> ra <*> ask'. Я думаю, что мы можем видеть проблему в этом свете: «Поведение» не имеет аналога «runReader». –

2

Как Петр уже указывалось, такая функция

flatten :: Behavior t [Behavior t a] -> Behavior t [a] 

существует тогда и только если тип Behavior t был монадой.

Здесь прямой путь, чтобы увидеть это:

join :: Behavior t (Behavior t a) -> Behavior t a 
join = map head . flatten . map (:[]) 

flatten = join . map sequence 

Однако, по разным причинам, Behavior tэто не монады в реакционно-банане. Это explained here.

Смежные вопросы