Open passy opened 9 years ago
Strict records are not yet supported. However I plan to implement support for them in the next major release.
@nikita-volkov Excellent, thanks for the reply. I updated the title accordingly, if you want to keep this for your backlog. :)
@nikita-volkov how are you planning to do that? As I see it, the strictness specifier lives outside of the type. For example, for a data constructor, NormalC
expects [(Strictness, Type)]
, but the Record quasiquoter only goes upto the type. Am I seeing something wrong?
@rabipelais Simple. Same as with tuples, there'll be two kinds of records: the one with all fields lazy and the one with all fields strict. The development branch demonstrates the projected syntax for both. The discussion and criticism is welcome.
If you want specific fields to be lazy while others are not, you could wrap the lazy field in data Thunk a = Thunk a
. Maybe it's worth the trouble to have the quasiquoter automagically wrap/unwrap Thunk so that accessing a lazy field foo doesn't mean writing [l|foo.unthunk1|]
. For example [l|foo|]
might expand out to whateverFooDoesRightNow . unthunk
. unthunk
and unthunk1
might be defined like in https://gist.github.com/aavogt/3d4347f4fc8ca850c6a0
@aavogt Seems like it would require too much sacrifices for little gain. Introduction of implicit "unthunk" would make the machinery behind records much harder to understand, while an important point of this project is the simplicity of the concept. Also this would introduce a memory footprint overhead for lazy records, thus nullifying a very important advantage of the library compared to HList-based solutions.
I guess you can avoid the one extra pointer introduced by Thunk
if you have newtypes that all involved functions actually listen to when deciding a value should be forced:
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Lens
newtype Lazy a = Lazy a deriving Show
newtype Bang a = Bang a deriving Show
-- not sure if anybody cares about the outer Bang/Lazy
_1BL f (Bang (Lazy a,b)) = f a <&> \a' -> Bang (Lazy a', b)
_1BB f (Bang (Bang !a,b)) = f a <&> \ !a' -> Bang (Bang a', b)
_1LL f (Lazy ~(Lazy a,b)) = f a <&> \a' -> Lazy (Lazy a', b)
_1LB f (Lazy ~(Bang !a,b)) = f a <&> \ !a' -> Lazy (Bang a', b)
class F1 o i where
f1 :: Lens (o (i x,y)) (o (i x',y)) x x'
instance F1 Bang Lazy where f1 = _1BL
instance F1 Bang Bang where f1 = _1BB
instance F1 Lazy Bang where f1 = _1LB
instance F1 Lazy Lazy where f1 = _1LL
I'd be interested if you can actually measure data Thunk
slowing things down: in the last benchmark in http://code.haskell.org/~aavogt/HList-benchmark/a.html, lookups in HList don't show up as slower than tuples/data until you get up to 10 elements, is 10 extra pointer dereferences as far as I know.
Total Haskell beginner here, so please excuse my ignorance if this is something obvious or unrelated. :)
This vanilla example compiles just fine
… but when wrapping it with Record like this
… I see this error
… referring to the
queue
declaration. I guess this would also benefit from #4, but I'm not sure whether this is me doing something wrong or whether the parser doesn't understand this construct.