May goal concerned with creating a new Semigroup type class instance for newly defined datatype in Haskell (For those who knows the "Get programming with Haskell" book by Will Kurt, I may refer you to the page 428,i.e. the end of the capstone project 5 with exercise extension).
There is a newly defined datatype:
data HINQ m a b = HINQ (m a -> m b) (m a) (m a -> m a)
| HINQ_ (m a -> m b) (m a)
This datatype designates the SQL-like query, where m
defines the context (Monad or Alternative), (m a -> m b)
is the function whose goal is similar to SQL function SELECT
,i.e. defines the property kind one wants to see in a database, (m a)
is a "table" to which applies the previous function (similar to SQL's table_name) and finally (m a -> m a)
filters out the property one is seeking for (similar to SQL's WHERE
).
My goal is to make this datatype an instance of a Semigroup (and finally a Monoid). It is worth mentioning that all needed Semigroup instances for a
, b
etc are assumed.
instance (Semigroup a, Semigroup (m a), Semigroup b,...) =>
Semigroup (HINQ m a b) where
(<>) (HINQ func1 start1 test1)
(HINQ func2 start2 test2) =
So the rough idea (on the background to see it clearer) of it is to make it possible to compose several different queries to a database into a single query, but I couldn't come up with an idea how to merge two different functions of type (m a -> m b)
into one at the same time merging two tables (m a)
... The first idea was to combine them into lists but then the type signature changes I haven't found yet the solution to this.
HINQ
- so this might be leading you towards the wrong solution, but ifm
is Applicative (which it will be if as you say it's a Monad or Alternative) anda
is a semigroup thenm a
can be automatically made a semigroup vialiftA2 (<>)
. (Not sure how to prove that will necessarily be associative but I'm sure it must fall out of the Applicative laws in some way.) – Robin ZigmondSemigroup
instance for this type, and it may even be law-abiding. (in fact, there's a trivial one - lift the existingSemigroup
instances for each component of the 3-tuple). But this instance is not unique, so theSemigroup
laws won't guide you here. You should first start by writing out a couple of example values forHINQ
and decided how you want the result of their semigroup addition to look like. – user2407038(m a -> m b)
, which (on the background purpose) should take a "database", e.g. aList
of some dataa
and extract needed information and return this data in a formList b
for example. The problem is if I have two different functions f1 and f2 of type(m a -> m b)
and two datasets of typem a
(let us forget for a moment of the third one) and then I would like to merge these functions and datasets to one object for each in order to represent two queries as one. – A. Gonus[String] -> [String]
? e.g what's the result ofdrop 10 <> take 20
? What aboutreverse <> id
orreverse <> reverse
? As it stands your question is underspecified - there are many implementations of<>
which would satisfy the semigroup law and all do different things for the examples above. What behavior do you actually want? – user2407038