<div dir="ltr">I haven't read all the code, but it seems to me that the most likely candidate is that your old <*> is breaking the applicative laws.  <*> "can't" depend on the values it's applied to (but based on what you said, it looks like your old <*> was making choices)</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 26, 2015 at 11:24 AM, martin <span dir="ltr"><<a href="mailto:martin.drautzburg@web.de" target="_blank">martin.drautzburg@web.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Am 03/24/2015 um 04:13 AM schrieb Chris Wong:<br>
<span class="">> Hi Martin,<br>
><br>
> On Tue, Mar 24, 2015 at 10:02 AM, martin <<a href="mailto:martin.drautzburg@web.de">martin.drautzburg@web.de</a>> wrote:<br>
>> Hello all,<br>
>><br>
>> I've been playing with temporal values, i.e. values which change over time at discrete points in time. I thought it<br>
>> would be good to make it an instance of Applicative and I was pleased with the results. I may be re-inventing some of<br>
>> frp here, but hey.<br>
<br>
><br>
</span><span class="">> Have you considered making Temporal a Monad? All monads by definition<br>
> provide a `join :: m (m a) -> m a` which flattens their nested<br>
> structure.<br>
<br>
</span>I just tried that, but I started with join and I wanted to get >>= for free.<br>
<span class=""><br>
data Change a = Chg {<br>
            ct :: Time, -- "change time"<br>
            cv :: a     -- "change value"<br>
        }<br>
<br>
data Temporal a = Temporal {<br>
    td :: a,         -- "temporal default"<br>
    tc :: [Change a] -- "temporal changes"<br>
} deriving (Show)<br>
<br>
</span>-- apply a function to the value of a change<br>
cvf :: (a->b) -> Change a -> Change b<br>
cvf f e = Chg (ct e) (f $ cv e)<br>
<br>
<br>
instance Functor Temporal where<br>
        fmap f (Temporal xd xs) = Temporal (f xd) (map (cvf f) xs)<br>
<br>
<br>
I beleive join is a bit too long to post here. But is seems to work with these examples<br>
<br>
exNat :: Temporal Int<br>
exNat  = Temporal 0 (map (\x -> Chg (2*x) (fromIntegral x)) [1..100000])<br>
<br>
ext2 :: Temporal Int<br>
ext2   = Temporal 10 [Chg 5 0]<br>
<br>
exNested2 = Temporal exNat [Chg 7 ext2]<br>
<br>
*Main> tJoin exNested2<br>
Temporal {td = 0, tc = [(2,1),(4,2),(6,3),(7,10)]}<br>
<br>
It starts with exNat but only up to the Time=10 where ext2 is scheduled and adds the default at Time=10. Since ext2 has<br>
no further changes after Time=10, this is it.<br>
<br>
<br>
Then I defined Modad as<br>
<br>
instance Monad Temporal where<br>
        return x    = Temporal x []<br>
        ma >>= f    = tJoin $ fmap f ma<br>
<br>
<br>
And Applicative<br>
<br>
instance Applicative Temporal where<br>
        pure x = Temporal x []<br>
        (<*>)  = ap<br>
<br>
<br>
But here is what I get<br>
<br>
*Main> (*) <$> exNat <*> ext2<br>
Temporal {td = 0, tc = [(2,10),(4,20),(6,30),(8,40),(10,50) ...<br>
<br>
This is NOT what I expected. Before I had a hand-crafted <*> function, and this gave me<br>
<br>
*Main> (*) <$> exNat <*> ext2<br>
Temporal {td = 0, tc = [(2,10),(4,20),(5,0),(6,0),(8,0) ...<br>
<br>
You see the values all drop to zero beyond Time=5, because ext2 drops to zero there and I am multiplying.<br>
<br>
Where do you think things went awry? Do you think its my tJoin function, or is there something wrong in the way I<br>
defined those typeclasses with respect to each other? Or did I voilate one of the laws? How could I find out?<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br></div>