agentm / project-m36

Project: M36 Relational Algebra Engine
The Unlicense
876 stars 47 forks source link

Define a Tupleable instance with a subrelation #351

Open Valdsonjr opened 1 year ago

Valdsonjr commented 1 year ago

Right now, haskell datatypes with list attributes are derived as t :: List (a :: SomeTypeT) is there a way of forcing the deriving mechanism to use t :: relation {a::SomeTypeT} instead?

YuMingLiao commented 1 year ago

I couldn't find the code but I once wrote something like an instance Atomable a => Atomable Set a where toAtom = -- relation{element a}) And the Tupleable deriving mechanism works pretty well.

For what its worth, relation{element a} is a set and cannot keep duplicated elements while relation{index Integer, element a} can.

Valdsonjr commented 1 year ago

Thanks, I will try that!

Do you guys think it's something useful to have? Should I make a pull request?

agentm commented 1 year ago

A shortcut here could be to wrap the specific list item with newtype and add an Atomable instance for it that does what you want. In general, Tupleable and Atomable don't support subrelations by default because doing so would make the type variables more annoying.

Certainly, if you make some progress on this front, a PR would be much appreciated.

agentm commented 1 year ago

@Valdsonjr , were you able to resolve this issue?

Valdsonjr commented 1 year ago

@agentm I made it work with this ugly thing:

{-# LANGUAGE ScopedTypeVariables #-}

-- 'throws' something that is not a member of the Exception type class
throwIfLeft :: (Show a) => Either a b -> b
throwIfLeft = either (error . show) id

instance (Tupleable a, NFData a, Ord a, Serialise a, Show a) => Atomable (Set a) where
    toAtom :: Set a -> Atom
    toAtom set = RelationAtom (Relation attrs tuples)
        where
        tuples = RelationTupleSet $ map toTuple $ toList set
        attrs = toAttributes (Proxy :: Proxy a)

    fromAtom :: Atom -> Set a
    fromAtom (RelationAtom (Relation _ (RelationTupleSet tuples))) =
        fromList $ map (throwIfLeft . fromTuple) tuples
    fromAtom _ = error "wrong Atom constructor for (Set a)"

    toAtomType :: proxy (Set a) -> AtomType
    toAtomType _ = RelationAtomType (toAttributes (Proxy :: Proxy a))

I really wish I could remove some of those constraints, but at least it works for my toy programs

agentm commented 1 year ago

That code is pretty straightforward- I'll wrap it into Project:M36, if you don't mind.

What bothers you about the constraints?

Valdsonjr commented 1 year ago

@agentm Sure! I can open the PR tomorrow night if you want. (and add the toAddTypeExpr)

What bothers you about the constraints?

I felt like there were too many constraints but on second thought I don't know of any other way