2

I've been playing around with Arrowized FRP libraries in Haskell (Yampa, in particular), but I can't quite figure out how to do "continual" switching. By that I mean that a signal passes through a signal function (sf below) which is itself a signal (as drawn in the upper half of the image).

Continual switching

Since I don't know ahead of time what the parameters of the switch will be, I can't see how to reduce this to a simpler, binary switch.

How then should one do it, if it's possible at all? I'd prefer Yampa code, but am happy with any Arrowized FRP code. I haven't tried other libraries (e.g. Sodium or Reactive Banana) to know whether I'd have the same confusion in those cases, but I'm curious about them too.

EDIT

To make this clearer an more concrete, I've labeled the image; possible types for the labels are:

  • in: Either Int (Int -> Int)

  • 1: (Int -> Int) -> (Either Int (Int -> Int) -> (Int -> Int))

  • sf could be:

(Either Int (Int -> Int) -> (Int -> Int)) -> Either Int (Int -> Int) -> (Int -> Int)

(e.g., app). But that's only if the part labeled with a question mark represents an input into sf. If it represents a more complex switch, the type would be

(Either Int (Int -> Int) -> (Int -> Int)) -> (Int -> Int)

instead.

  • 2 and out are pretty much irrelevant.

The idea is that I want the circuit to behave as if sf were app, with the signal labeled f representing the function that is applied to in, and with in itself being the source of both the arguments to fs, and the fs themselves. I want to get a circuit that can process inputs and change it's behavior (the signal functions that constitute it) dynamically based on those inputs.

On the one hand, it seems to me like sf can't in fact be app, since in this case we don't have an ArrowApply; but on the other hand I imagine that same behavior can be achieved with some form of sophisticated switching.

user2141650
  • 2,827
  • 1
  • 15
  • 23
  • 2
    Before someone knowledgable comes along I'll just suggest the naive approach: does `ArrowLoop` give you what you want? – Tom Ellis Nov 18 '13 at 14:52
  • I can see how it would if SF were an instance of ArrowApply, but otherwise I don't immediately see how it helps. – user2141650 Nov 20 '13 at 13:15
  • Could you give the type of `sf` (and also what looks like two `Arrow`s combined with `&&&`)? I think that would help me understand what's going on. – Tom Ellis Nov 20 '13 at 18:09
  • I edited the question - let me know if it's still unclear. – user2141650 Nov 20 '13 at 21:18

2 Answers2

2

You're asking to have an arrow that's output by an arrow to be used as an arrow. That's what app from ArrowApply is for.

If you want to use that in some looped construct like your diagram, you might need ArrowLoop, but actually the do notation allows you to be fairly flexible with all this stuff anyway.

There's quite a lengthy explanation of app in this answer but I'll copy the main relevant bit:


What does app exactly do? it's type doesn't even have an (->) It lets you use the output of an arrow as an arrow. Let's look at the type.

app :: ArrowApply m => m (m b c, b) c

I prefer to use m to a because m feels more like a computation and a feels like a value. Some people like to use a type operator (infix type constructor), so you get

app :: ArrowApply (~>) => (b ~> c, b) ~> c

We think of b ~> c as an arrow, and we think of an arrow as a thing which takes bs, does something and gives cs. So this means app is an arrow that takes an arrow and a value, and can produce the value that the first arrow would have produced on that input.

It doesn't have -> in the type signature because when programming with arrows, we can turn any function into an arrow using arr :: Arrow (~>) => (b -> c) -> b ~> c, but you can't turn every arrow into a function, thus (b ~> c, b) ~> c is usable where (b ~> c, b) -> c or (b -> c, b) ~> c would not be.

Community
  • 1
  • 1
some guy
  • 23
  • 1
  • 5
1

I still think it's a case of ArrowLoop!

You have

in :: Arr () A
sf :: Arr (A -> B, A) B
one :: Arr B (A -> B)
two :: Arr B C

sf is just arr (uncurry ($)).

Then you have sf >>> (one &&& two) :: Arr (A -> B, A) (A -> B, C) and you can use loop (or rather loop with arr swap judiciously placed) to get an Arr A C.

Will that give you what you want?

Tom Ellis
  • 9,224
  • 1
  • 29
  • 54
  • Aha! First, thanks for picking better types than I did. Second - I think I see the point here. I somehow didn't think to enclose the loop over the larger circuit (`sf >>> (one &&& two)`). But it looks like you're right. `loop $ arr swap >>> (sf >>> (one &&& two)) >>> arr swap` has the right type, and everything typechecks. I'm almost certain that answers the question perfectly, but give me a few more minutes to be sure. – user2141650 Nov 20 '13 at 23:06
  • Great! Do come back with more questions if you have any. – Tom Ellis Nov 21 '13 at 02:42