
I'm investigating unboxed types in GHC 9.2. Levity polymorphism seems to be severely limited in a way that makes it hard to envisage a Haskell ecosystem which comfortably combines lifted and unlifted types. Am I missing something? Understandably, the following attempt at defining a RuntimeRep-polymorphic identity does not work: myId1 :: forall (r :: RuntimeRep) (t :: TYPE r). t -> t myId1 x = x The GHC Users Guide explains why[1]. It's impossible to generate code for myId1 because there is no way of determining the machine representation of the argument x. But worse, it's not even possible to define a *Levity*-polymorphic identity: myId2 :: forall (lev :: Levity) (t :: TYPE (BoxedRep lev)). t -> t myId2 x = x In this case the argument can only have kind TYPE LiftedRep or TYPE UnliftedRep. The machine representation is the same in each case. The problem this time is that the code generator doesn't know whether it should emit code to evaluate the argument (UnliftedRep case) or not (LiftedRep case). But this seems like a solvable problem. Surely a KnownLevity type class (possibly magical) could solve the problem. This seems like it should work myId3 :: forall (lev :: Levity) (t :: TYPE (BoxedRep lev)). KnownLevity lev => t -> t myId3 x = x and in fact I wouldn't be surprised if this could be made to work: myId4 :: forall (r :: RuntimeRep) (t :: TYPE r). KnownRuntimeRep r => t -> t myId4 x = x So what is the situation here? 1. myId3 already works (then where is KnownLevity made available and why isn't it mentioned in the Users Guide?) 2. myId3 can never work (then why not?) 3. myId3 might be able to work but it's an open research problem (then who is working on it, if anyone?) 4. myId3 would work and it would be useful but no one's proposed or implemented it (then who would be the best person to collaborate with on that?) 5. myId3 would work but it would not actually be useful (then what have I misunderstood?) I suspect the answer is 1 (or maybe 4) based on the following passage in the Levity Polymorphism[2] paper by RE & SPJ[2]:
users can use a runtime type check (though GHC’s Typeable feature) to determine the memory representation of an as-yet- unbound argument to a function
(and the same questions for myId4). Thanks, Tom [1] https://downloads.haskell.org/~ghc/9.4.4/docs/users_guide/exts/representatio... [2] https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/levity-p...

I think theoretically a type class is indeed all you need even for representation polymorphism. I believe that is what the Sixten language [1] does. Currently GHC rejects any levity polymorphic function arguments and local binders. Issue #15532 [2] tracks the possibility of relaxing these restrictions. The type class approach is mentioned in that thread. I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away and another suggestion that functions that are always guaranteed to inline can also be allowed to be representation polymorphic. But I can’t find this thread again. Also, I think the identity function is so simple that you don’t even need the KnownLevity class for levity polymorphism. The implementation can just copy the pointer from the input to the output. Cheers, Jaro [1] https://github.com/ollef/sixten [2] https://gitlab.haskell.org/ghc/ghc/-/issues/15532
On 2 Jan 2023, at 13:02, Tom Ellis
wrote: I'm investigating unboxed types in GHC 9.2. Levity polymorphism seems to be severely limited in a way that makes it hard to envisage a Haskell ecosystem which comfortably combines lifted and unlifted types. Am I missing something?
Understandably, the following attempt at defining a RuntimeRep-polymorphic identity does not work:
myId1 :: forall (r :: RuntimeRep) (t :: TYPE r). t -> t myId1 x = x
The GHC Users Guide explains why[1]. It's impossible to generate code for myId1 because there is no way of determining the machine representation of the argument x.
But worse, it's not even possible to define a *Levity*-polymorphic identity:
myId2 :: forall (lev :: Levity) (t :: TYPE (BoxedRep lev)). t -> t myId2 x = x
In this case the argument can only have kind TYPE LiftedRep or TYPE UnliftedRep. The machine representation is the same in each case. The problem this time is that the code generator doesn't know whether it should emit code to evaluate the argument (UnliftedRep case) or not (LiftedRep case). But this seems like a solvable problem. Surely a KnownLevity type class (possibly magical) could solve the problem. This seems like it should work
myId3 :: forall (lev :: Levity) (t :: TYPE (BoxedRep lev)). KnownLevity lev => t -> t myId3 x = x
and in fact I wouldn't be surprised if this could be made to work:
myId4 :: forall (r :: RuntimeRep) (t :: TYPE r). KnownRuntimeRep r => t -> t myId4 x = x
So what is the situation here?
1. myId3 already works (then where is KnownLevity made available and why isn't it mentioned in the Users Guide?)
2. myId3 can never work (then why not?)
3. myId3 might be able to work but it's an open research problem (then who is working on it, if anyone?)
4. myId3 would work and it would be useful but no one's proposed or implemented it (then who would be the best person to collaborate with on that?)
5. myId3 would work but it would not actually be useful (then what have I misunderstood?)
I suspect the answer is 1 (or maybe 4) based on the following passage in the Levity Polymorphism[2] paper by RE & SPJ[2]:
users can use a runtime type check (though GHC’s Typeable feature) to determine the memory representation of an as-yet- unbound argument to a function
(and the same questions for myId4).
Thanks,
Tom
[1] https://downloads.haskell.org/~ghc/9.4.4/docs/users_guide/exts/representatio...
[2] https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/levity-p... _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I think theoretically a type class is indeed all you need even for representation polymorphism. I believe that is what the Sixten language [1] does.
Currently GHC rejects any levity polymorphic function arguments and local binders. Issue #15532 [2] tracks the possibility of relaxing these restrictions. The type class approach is mentioned in that thread.
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away and another suggestion that functions that are always guaranteed to inline can also be allowed to be representation polymorphic. But I can’t find this thread again.
Very helpful info, thanks Jaro!

On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this? https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258...

No, I found it. It is this GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/14917
On 2 Jan 2023, at 15:07, Tom Ellis
wrote: On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this?
https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258... _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

i've written (more opaquely than i'd like), about this topic a few times ,
including on that ticket
https://gitlab.haskell.org/ghc/ghc/-/issues/14917#note_230433 !
ultimately, you want some notion of function types /lambdas that have the
equivalent to the C++ Const-Eval / C++ Template arg "compile time
instantiation is the only allowed flavor".
for the particulars in the context of runtime rep levity, my intuitions
break down, but i've had examples of the sort of "must be resolved at
compile time" where for the behavior i'd need isn't expressible using type
classes because those can be instantiated abstractly rather than
concretely and still be valid programs.
granted i'm not terribly current on the state of play in >= ghc 9.4 for
this stuff, but i would not be surprised if the architectural hooks needed
for a "strict staging lambda" arent there yet. (you can manufacture some of
this stuff with typed template haskell, BUT theres no mechanism for
expressing the primops that certain uses cases, like SIMD shuffle, would
need)
On Mon, Jan 2, 2023 at 9:18 AM J. Reinders
No, I found it. It is this GHC issue:
https://gitlab.haskell.org/ghc/ghc/-/issues/14917
On 2 Jan 2023, at 15:07, Tom Ellis < tom-lists-haskell-cafe-2017@jaguarpaw.co.uk> wrote:
On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this?
https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258...
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

For what it's worth, this initiative may get a significant boost soon. My main job at Jane Street these days is designing & implementing unboxed types for OCaml (which has never really had them, unlike their long history within GHC). There is much eagerness to use unboxed types. But we've realized that, to meet these expectations, we'll need the equivalent of levity polymorphism. So I'll be spending some time over the next few months (I think) putting together the design there. Once it starts to come together, I can share it and then work to adapt it to Haskell. Though as I'm writing this, I see a really easy way to do this in Haskell. (Sadly for me, it won't work in OCaml.) Representation polymorphism can be made to work today via type classes. That is, we have a `class Representation (r :: RuntimeRep)` whose dictionaries have instructions for how to store variables whose types have kind TYPE r, and also to apply functions to such variables. There's no good way to mock this up today because GHC requires a known RuntimeRep in order to bind a variable, but using instructions in a dictionary is possible instead. This would work just fine -- except that it would be very slow, because it means every store or function-apply requires a dictionary access. It would be disastrous. However, GHC *already* has machinery for specializing functions to work with known dictionaries. All you would have to do is to ensure that all Representation dictionaries get specialized away; this could be done with a straightforward check (even implementable in a core plugin). So programmers can be polymorphic over representations, and GHC has to work hard to specialize. What this is missing is a nice mechanism for helping the programmer avoid cases that GHC can't specialize -- but that could be added later. I really think this would just work, quite easily. Well, "easily" from a language-design standpoint. An efficient implementation in GHC would be fiddly, because you'd need to annotate every variable with information about its representation: either it's known (good), or it's not, and then the variable's representation is informed by a specific dictionary. I think this could probably all be tracked efficiently, but it wouldn't surprise me if there's a measurable slowdown in compilation times to track these representations. And infer them. Left unaddressed here: how to make datatypes representation-polymorphic, which requires a lower-level understanding of data-constructor representations than I have. Richard
On Jan 6, 2023, at 11:51 AM, Carter Schonwald
wrote: i've written (more opaquely than i'd like), about this topic a few times , including on that ticket https://gitlab.haskell.org/ghc/ghc/-/issues/14917#note_230433 https://gitlab.haskell.org/ghc/ghc/-/issues/14917#note_230433 !
ultimately, you want some notion of function types /lambdas that have the equivalent to the C++ Const-Eval / C++ Template arg "compile time instantiation is the only allowed flavor".
for the particulars in the context of runtime rep levity, my intuitions break down, but i've had examples of the sort of "must be resolved at compile time" where for the behavior i'd need isn't expressible using type classes because those can be instantiated abstractly rather than concretely and still be valid programs.
granted i'm not terribly current on the state of play in >= ghc 9.4 for this stuff, but i would not be surprised if the architectural hooks needed for a "strict staging lambda" arent there yet. (you can manufacture some of this stuff with typed template haskell, BUT theres no mechanism for expressing the primops that certain uses cases, like SIMD shuffle, would need)
On Mon, Jan 2, 2023 at 9:18 AM J. Reinders
mailto:jaro.reinders@gmail.com> wrote: No, I found it. It is this GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/14917 https://gitlab.haskell.org/ghc/ghc/-/issues/14917
On 2 Jan 2023, at 15:07, Tom Ellis
mailto:tom-lists-haskell-cafe-2017@jaguarpaw.co.uk> wrote: On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this?
https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258... https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258... _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Very interesting. A few thoughts about potential rough spots:
Representation polymorphism can be made to work today via type classes. That is, we have a `class Representation (r :: RuntimeRep)` whose dictionaries have instructions for how to store variables whose types have kind TYPE r, and also to apply functions to such variables. There's no good way to mock this up today because GHC requires a known RuntimeRep in order to bind a variable, but using instructions in a dictionary is possible instead. This would work just fine -- except that it would be very slow, because it means every store or function-apply requires a dictionary access. It would be disastrous.
It would also mean that even to access non-polymorphic function arguments (of a representation-polymorphic function), you would potentially need to consult the dictionaries for all preceding parameters, and that would vary depending on the calling conventions for a particular platform. For example, if a function takes a representation-polymorhpic first parameter and a (non-polymoprhic) unboxed float as its second parameter, then where to find that float would change if the first parameter ends up being an unboxed float. (Or rather, it would probably change for a register-based calling convention and possibly not change for a stack-based calling convention.) That is, assuming the the calling convention for representation-polymorphic function should be the same, once instantiated for a particular representation, as a non-representation-polymorphic function whose arguments have those particular representations. So that means the generated assembly for such a representation-polymorphic function would have to include code to figure all of that out per-invocation. [This is all just about the case of having a single non-specialized implementation as the outcome of compilation.] So that does seem conceptually possible but practically...perhaps not.
However, GHC *already* has machinery for specializing functions to work with known dictionaries. All you would have to do is to ensure that all Representation dictionaries get specialized away; this could be done with a straightforward check (even implementable in a core plugin). So programmers can be polymorphic over representations, and GHC has to work hard to specialize. What this is missing is a nice mechanism for helping the programmer avoid cases that GHC can't specialize -- but that could be added later. I really think this would just work, quite easily.
At first glance, it seems like these dictionaries would be just like any other typeclass dictionaries in terms of the possibility of specializing them away (right?), so I wonder how much of the time that is possible. That is, I wonder if the programmer would run into forbidden cases commonly, and how limiting that would be. For instance, could you have a representation-polymorphic `fold` (e.g., which you might call with an unboxed int accumulator value, with a matching accumulator function)? I assume you couldn't have a rank-2 representation-polymorphic function? (That is, you couldn't have a representation-polymorphic unknown function. Is that right?) Just sort of thinking out loud. [I've watched your Tweag videos about Levity Polymorphism but I haven't read the paper, so I hope I'm not asking questions that were already covered there. I need to read the paper!] Thanks, Jeff
On Jan 7, 2023, at 10:20 AM, Richard Eisenberg
wrote: For what it's worth, this initiative may get a significant boost soon. My main job at Jane Street these days is designing & implementing unboxed types for OCaml (which has never really had them, unlike their long history within GHC). There is much eagerness to use unboxed types. But we've realized that, to meet these expectations, we'll need the equivalent of levity polymorphism. So I'll be spending some time over the next few months (I think) putting together the design there. Once it starts to come together, I can share it and then work to adapt it to Haskell.
Though as I'm writing this, I see a really easy way to do this in Haskell. (Sadly for me, it won't work in OCaml.) Representation polymorphism can be made to work today via type classes. That is, we have a `class Representation (r :: RuntimeRep)` whose dictionaries have instructions for how to store variables whose types have kind TYPE r, and also to apply functions to such variables. There's no good way to mock this up today because GHC requires a known RuntimeRep in order to bind a variable, but using instructions in a dictionary is possible instead. This would work just fine -- except that it would be very slow, because it means every store or function-apply requires a dictionary access. It would be disastrous. However, GHC *already* has machinery for specializing functions to work with known dictionaries. All you would have to do is to ensure that all Representation dictionaries get specialized away; this could be done with a straightforward check (even implementable in a core plugin). So programmers can be polymorphic over representations, and GHC has to work hard to specialize. What this is missing is a nice mechanism for helping the programmer avoid cases that GHC can't specialize -- but that could be added later. I really think this would just work, quite easily.
Well, "easily" from a language-design standpoint. An efficient implementation in GHC would be fiddly, because you'd need to annotate every variable with information about its representation: either it's known (good), or it's not, and then the variable's representation is informed by a specific dictionary. I think this could probably all be tracked efficiently, but it wouldn't surprise me if there's a measurable slowdown in compilation times to track these representations. And infer them.
Left unaddressed here: how to make datatypes representation-polymorphic, which requires a lower-level understanding of data-constructor representations than I have.
Richard
On Jan 6, 2023, at 11:51 AM, Carter Schonwald
wrote: i've written (more opaquely than i'd like), about this topic a few times , including on that ticket https://gitlab.haskell.org/ghc/ghc/-/issues/14917#note_230433 !
ultimately, you want some notion of function types /lambdas that have the equivalent to the C++ Const-Eval / C++ Template arg "compile time instantiation is the only allowed flavor".
for the particulars in the context of runtime rep levity, my intuitions break down, but i've had examples of the sort of "must be resolved at compile time" where for the behavior i'd need isn't expressible using type classes because those can be instantiated abstractly rather than concretely and still be valid programs.
granted i'm not terribly current on the state of play in >= ghc 9.4 for this stuff, but i would not be surprised if the architectural hooks needed for a "strict staging lambda" arent there yet. (you can manufacture some of this stuff with typed template haskell, BUT theres no mechanism for expressing the primops that certain uses cases, like SIMD shuffle, would need)
On Mon, Jan 2, 2023 at 9:18 AM J. Reinders
wrote: No, I found it. It is this GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/14917
On 2 Jan 2023, at 15:07, Tom Ellis
wrote: On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this?
https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258...

On Jan 9, 2023, at 9:52 PM, Jeff Clites
wrote: It would also mean that even to access non-polymorphic function arguments (of a representation-polymorphic function), you would potentially need to consult the dictionaries for all preceding parameters, and that would vary depending on the calling conventions for a particular platform. ... So that does seem conceptually possible but practically...perhaps not.
That's a good point about later parameters depending on earlier ones. I had been thinking that we need the information per parameter, but that's definitely wrong. We really need the parameters' representations on the -> in `\ x y z -> ...`, not on the x, y, z. Still doable. But definitely not pleasant.
At first glance, it seems like these dictionaries would be just like any other typeclass dictionaries in terms of the possibility of specializing them away (right?), so I wonder how much of the time that is possible. That is, I wonder if the programmer would run into forbidden cases commonly, and how limiting that would be.
This is a good question, one I share.
For instance, could you have a representation-polymorphic `fold` (e.g., which you might call with an unboxed int accumulator value, with a matching accumulator function)?
Yes. This is a case where the representation would be statically known, and thus specialized away. All good.
I assume you couldn't have a rank-2 representation-polymorphic function? (That is, you couldn't have a representation-polymorphic unknown function. Is that right?)
This sounds like a case where we can't specialize away. The "cheap and cheerful" version of this simply tries to specialize. If any dictionaries are left after all specialization is complete, we error. This is poor for users, because it makes it very hard / impossible for a user to predict whether their program will be accepted. Put another way, this cheap-and-cheerful approach lacks a declarative specification of what programs are accepted. A more glorious approach, tracking which computations/specializations can be done at compile time, would solve this. That more glory is a large part of what I'll be looking at over the next few months.
Just sort of thinking out loud. [I've watched your Tweag videos about Levity Polymorphism but I haven't read the paper, so I hope I'm not asking questions that were already covered there. I need to read the paper!]
These are great points in the conversation. You seem to understand this well. Thanks, Richard
Thanks,
Jeff
On Jan 7, 2023, at 10:20 AM, Richard Eisenberg
wrote: For what it's worth, this initiative may get a significant boost soon. My main job at Jane Street these days is designing & implementing unboxed types for OCaml (which has never really had them, unlike their long history within GHC). There is much eagerness to use unboxed types. But we've realized that, to meet these expectations, we'll need the equivalent of levity polymorphism. So I'll be spending some time over the next few months (I think) putting together the design there. Once it starts to come together, I can share it and then work to adapt it to Haskell.
Though as I'm writing this, I see a really easy way to do this in Haskell. (Sadly for me, it won't work in OCaml.) Representation polymorphism can be made to work today via type classes. That is, we have a `class Representation (r :: RuntimeRep)` whose dictionaries have instructions for how to store variables whose types have kind TYPE r, and also to apply functions to such variables. There's no good way to mock this up today because GHC requires a known RuntimeRep in order to bind a variable, but using instructions in a dictionary is possible instead. This would work just fine -- except that it would be very slow, because it means every store or function-apply requires a dictionary access. It would be disastrous. However, GHC *already* has machinery for specializing functions to work with known dictionaries. All you would have to do is to ensure that all Representation dictionaries get specialized away; this could be done with a straightforward check (even implementable in a core plugin). So programmers can be polymorphic over representations, and GHC has to work hard to specialize. What this is missing is a nice mechanism for helping the programmer avoid cases that GHC can't specialize -- but that could be added later. I really think this would just work, quite easily.
Well, "easily" from a language-design standpoint. An efficient implementation in GHC would be fiddly, because you'd need to annotate every variable with information about its representation: either it's known (good), or it's not, and then the variable's representation is informed by a specific dictionary. I think this could probably all be tracked efficiently, but it wouldn't surprise me if there's a measurable slowdown in compilation times to track these representations. And infer them.
Left unaddressed here: how to make datatypes representation-polymorphic, which requires a lower-level understanding of data-constructor representations than I have.
Richard
On Jan 6, 2023, at 11:51 AM, Carter Schonwald
wrote: i've written (more opaquely than i'd like), about this topic a few times , including on that ticket https://gitlab.haskell.org/ghc/ghc/-/issues/14917#note_230433 !
ultimately, you want some notion of function types /lambdas that have the equivalent to the C++ Const-Eval / C++ Template arg "compile time instantiation is the only allowed flavor".
for the particulars in the context of runtime rep levity, my intuitions break down, but i've had examples of the sort of "must be resolved at compile time" where for the behavior i'd need isn't expressible using type classes because those can be instantiated abstractly rather than concretely and still be valid programs.
granted i'm not terribly current on the state of play in >= ghc 9.4 for this stuff, but i would not be surprised if the architectural hooks needed for a "strict staging lambda" arent there yet. (you can manufacture some of this stuff with typed template haskell, BUT theres no mechanism for expressing the primops that certain uses cases, like SIMD shuffle, would need)
On Mon, Jan 2, 2023 at 9:18 AM J. Reinders
wrote: No, I found it. It is this GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/14917
On 2 Jan 2023, at 15:07, Tom Ellis
wrote: On Mon, Jan 02, 2023 at 02:01:56PM +0100, J. Reinders wrote:
I seem to recall another thread where there were more suggestions like a special form of type classes that is always guaranteed to monomorphise away
Perhaps this?
https://github.com/ghc-proposals/ghc-proposals/pull/454#issuecomment-1030258...
participants (5)
-
Carter Schonwald
-
J. Reinders
-
Jeff Clites
-
Richard Eisenberg
-
Tom Ellis