patrickt / fastsum Goto Github PK
View Code? Open in Web Editor NEWA fast open-union type, suitable for 100+ contained alternatives.
License: Other
A fast open-union type, suitable for 100+ contained alternatives.
License: Other
The following code demonstrates the problem:
works :: (Apply Eq1 r, Eq v) => Sum r v -> Sum r v -> Bool
works x y = x == y
-- Could not deduce (Apply Eq1 (Const () : r))
fails :: (Apply Eq1 r, Eq v) => Sum r v -> Sum r v -> Bool
fails x y = weaken @_ @_ @(Const ()) x == weaken y
Of course, if I try to provide the missing instance it complains about overlap. So how do I convince it that if Apply Eq1 r
, then clearly Apply Eq1 (Const () : r)
, since there is both Eq1
for Const
and Eq
for ()
?
I've found these useful as a UI for fastsum
in my lens-oriented code:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Journal.SumLens where
import Control.Lens
import Data.Constraint
import Data.Sum
projected :: e :< r => Prism' (Sum r v) (e v)
projected = prism' inject project
projectedC :: forall r v e. Const e :< r => Prism' (Sum r v) e
projectedC = prism' (inject . Const) (fmap getConst . project)
weakened :: Prism' (Sum (e ': r) v) (Sum r v)
weakened = prism' weaken $ \s -> case decompose s of
Left es -> Just es
Right _ -> Nothing
_shead :: Prism' (Sum (e ': r) v) (e v)
_shead = projected
_stail :: Prism' (Sum (e ': r) v) (Sum r v)
_stail = weakened
underneath :: e :< r => Prism' (Sum (s ': r) v) (e v)
underneath = weakened . projected
underneathC :: Const e :< r => Prism' (Sum (s ': r) v) e
underneathC = weakened . projectedC
decomposed :: Iso' (Sum (e ': r) v) (Either (Sum r v) (e v))
decomposed = iso decompose (either weaken inject)
-- | @applied@ is the optic version of apply, to make it easy to compose
-- applications with other optics:
-- @@
-- s ^. applied @Printable printItem
-- === apply @Printable printItem s
-- @@
applied ::
forall c r v a.
Apply c r =>
(forall f. c f => f v -> a) ->
Fold (Sum r v) a
applied k f s = s <$ f (apply @c k s)
-- | @HasTraversal'@ serves the same role as Apply, but for traversals across
-- sums that support a given optic. For example, and with direct analogy to
-- 'Apply':
-- @@
-- class HasLot f where
-- _Lot :: Traversal' (f v) Lot
--
-- instance HasTraversal' HasLot fs => HasLot (Sum fs) where
-- _Lot = traversing @HasLot _Lot
-- @@
class HasTraversal' (c :: (* -> *) -> Constraint) (fs :: [* -> *]) where
traversing :: (forall g. c g => Traversal' (g a) b) -> Traversal' (Sum fs a) b
instance c t => HasTraversal' c '[t] where
traversing k f s = fmap inject (k f (decomposeLast s))
instance
{-# OVERLAPPING #-}
(HasTraversal' c (u ': r), c t) =>
HasTraversal' c (t ': u ': r)
where
traversing k f s = case decompose s of
Right e -> inject <$> k f e
Left es -> weaken <$> traversing @c k f es
When trying to build the package with cabal, I encounter the following error:
Resolving dependencies...
Configuring fastsum-0.1.1.0...
Preprocessing library for fastsum-0.1.1.0..
Building library for fastsum-0.1.1.0..
[1 of 2] Compiling Data.Sum.Templates ( src/Data/Sum/Templates.hs, dist/build/Data/Sum/Templates.o )
[2 of 2] Compiling Data.Sum ( src/Data/Sum.hs, dist/build/Data/Sum.o )
ghc: internal error: Unable to commit 1048576 bytes of memory
(GHC version 8.6.4 for x86_64_unknown_linux)
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
Failed to install fastsum-0.1.1.0
cabal: Error: some packages failed to install:
fastsum-0.1.1.0-GQUPDK7HNQ3BzBCRuqjYJ7 failed during the building phase. The
exception was:
ExitFailure (-6)
I'm using:
cabal-install version 2.4.1.0
compiled using version 2.4.1.0 of the Cabal library
This seems to be a memory problem and I observe the 4GB of the memory on the VM are consumed by the ghc
process before the failure.
Any help solving this issue would be great.
There are none. That's bad.
I'm trying to figure out how to get the following to work:
stronger :: f :< r => Sum r v -> a
stronger = undefined
weaker :: f :< r => Sum (e ': r) v -> a
weaker = stronger
I would think that f :> r
entails the constraint f :> any ': r
, but this does not seem to be the case. Intuitively I would see the entailment as just a Succ
on the former witness. Instead, the error I get is:
• Could not deduce (KnownNat (ElemIndex f0 (e : r)))
arising from a use of ‘stronger’
from the context: f :< r
bound by the type signature for:
weaker :: forall (f :: * -> *) (r :: [* -> *]) (e :: * -> *) v.
(f :< r) =>
Sum (e : r) v -> f v
at /Users/johnw/src/trade-journal/src/Journal/SumLens.hs:74:1-41
The type variable ‘f0’ is ambiguous
Relevant bindings include
weaker :: Sum (e : r) v -> f v
(bound at /Users/johnw/src/trade-journal/src/Journal/SumLens.hs:75:1)
ClosedTypeFamilyD
TySynEqn
got an extra parameter.
Once upon a time, fastsum
had separate Apply
and Apply1
typeclasses s.t. we could use Apply
for Show
and Apply1
for Functor
. We eventually got rid of the former because compile times were already far too high, and instead used Show1
to provide our Show
instance.
However, while it’s easy to derive Show
instances, Show1
is not derivable, so you have to do a bunch of extra work just to show your Sum
s.
The following typeclass makes it possible to "populate" a sum by attempting a series of operations in MonadPlus
, for example parsers:
class Producible m f where
produce :: m (f v)
class Populate m (fs :: [* -> *]) where
populate :: m (Sum fs b)
instance (Producible m t, MonadPlus m) => Populate m '[t] where
populate = fmap inject (produce @m @t)
instance
{-# OVERLAPPING #-}
(Populate m (u ': r), Producible m t, MonadPlus m) =>
Populate m (t ': u ': r)
where
populate =
fmap inject (produce @m @t)
<|> fmap weaken (populate @m @(u ': r))
This could be implemented for a Megaparsec type as follows:
instance Producible Parser (Const Entry) where
produce = fmap Const parseEntry
Now you can populate a Sum '[Const a, Const b, Const c] v
as long as there are parsers that can produce values of type a
, b
and c
.
Greetings!
We had talked about a combinator to decompose a sum which could be used in pattern matching. It would remove the head of the type list and return either the matched value or a sum with that type removed. Here's what I've got:
-- | Try to extract the first type from the sum. On failure, return a
-- sum that eliminates that as a possibility. This would probably have
-- to be exported by the library so we don't have to export the Sum
-- constructor.
decomposeSum :: Sum (e ': es) b -> Either (Sum es b) (e b)
decomposeSum sum@(Sum n v) = maybe (Left (Sum (n - 1) v)) Right (projectSum sum)
-- | For a sum with precisely one type in the type list, we can safely
-- project that value.
decomposeLast :: Sum '[e] b -> e b
decomposeLast = either (error "impossible") id . decomposeSum
Would you accept a PR with these combinators? Also, are there any other tasks I could help with to get this package ready for a hackage release?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.