Closed ugeorge closed 5 years ago
The solution can even be generalized considering how type traversals behave, and understanding that "unzipping" at its core is just a kind of transpose. While signal is a traversable type itself, tuple is not. It is still possible to create generic "traversable-like" rules for specific tuple instances as well, by following some patterns like in the implementation of "unzip" (|<
) utilities in ForSyDe-Atom.
For the scope of ForSyDe-Shallow, though, simple specialized solutions per each MoC should suffice.
George, I've found a simple way to solve the issue without the need to change the zipwhiths and unzips. So follow me on this one:
We want the type signature of the function inside the actor12SDF
(for instance) to be like
f1 :: [a] -> ([b], [c])
but instead, we are using
f2 :: [a] -> [([b], [c])]
because of the maps and zipwiths, as you said. We can make an actor12SDF
with f1
in the type signature, just as we want, and inside de definition of the actor we can transform f1
into f2
by doing
(\ a -> [f1 a])
and keep the zipwiths, unzips and all the rest of the function definition intact.
Therefore we do not need to change anything else. And we can do this with all the other actors as well. I don't think there is going to be a more simple/fast solution for this issue than that. I did something similar to CSDF and SADF and it is working fine.
Nice example, btw!
When you say fast solution are you referring to the amount of our work, or to performance? Because when it comes to performance, unnecessary type constructors, wrappings and unwrappings do take their toll. Let me try something out tonight and we will discuss our solutions tomorrow.
My plan is to define zipWithSDF for example as:
zipWithSDF :: .... -> ([a] -> [b] -> c) -> ....
And introduce an aditional utility for re-creating signals from streams of partitions (basically what the current unzipSDF
are doing). I believe this is also your approach for detector
s, so that you do not constrain the return type. Sure, this means a bit more work, but in the long run it is worth it.
Check this commit. The only thing exported are the actor
s and delay
s (i.e. initial tokens), because this is what the SDF MoC actually defines, and nothing more. One would have to come up with a really good case to defend map
, zipWith
and unzip
as part of any MoC, because I'm not buying it...
@ricardobonna , it seems that your approach is the safe one after all. The utilities I wrote seem to cause infinite loops in feedback systems (see issue above).
Currently SDF actors with multiple outputs take functions that yield lists of tuples of lists, e.g.
That is because, among others,
actor
s are implemented internally withmap
/zipWith
, which need to yield lists in order to recreate signals. Although just a "type fix", this leaves way for design mistakes, e.g.:How can the previous actor instance be interpreted? It is wrong. Situations like these need to be avoided simply by restricting the yields to tuples rather than lists of tuples. This is one by modifying
map
,zipWith
s andunzip
s accordingly. In this way the constructors do not comply to SDF any more, but this is not an issue, since they are not exported anyway. Onlyactor
s need to be exported. The rest should be regarded as utilities, and nothing more.