agentm / project-m36

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

Define a Tupleable instance with a subrelation #351

Open Valdsonjr opened 2 years ago

Valdsonjr commented 2 years 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 2 years 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 2 years ago

Thanks, I will try that!

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

agentm commented 2 years 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 2 years ago

@Valdsonjr , were you able to resolve this issue?

Valdsonjr commented 2 years 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 2 years 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 2 years 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