Just to make sure I understand. In my initial example, the following are all types and I wanted the dispatch to happen on this types once they are instances of the Taskable type class.Now, later on I expect users to create more types which are all say, instances of Taskable typeclass. So, here I do not expect to have any dispatch based on value, but based on types.
-- task 1
data UpdateAcctsTask = UpdateAccts
-- task 2
data EmailConfig = EmaiConfig {someattrs::String}
data SendEmailTask = SendEmailsTask EmailConfig
-- task 3
data GeneralWriterTask a = GeneralWriterTask aOn Wed, Mar 1, 2017 at 5:24 AM, Patrick Chilton <chpatrick@gmail.com> wrote:Is that thinking usually an anti-pattern.Typeclasses choose between implementations of a method based on static types known at compile time. In OOP, which implementation of an interface method you get depends on the run-time object instance. They're not really related despite the similarities.For example, if you have a list of widgets and you want to do something different depending on what their run-time value is, a typeclass would be the wrong thing to use since it dispatches on types, not values. It's possible to make them work a little bit like OOP classes, but then you end up with the classic antipattern.On Wed, Mar 1, 2017 at 2:16 PM, Guru Devanla <gurudev.devanla@gmail.com> wrote:The existential antipattern. link was very useful and made me re-asses my inclination to defining type classes and embedded types right away.Secondly, while choosing the type-class approach, I imagined all these required class methods to be an interface and therefore an interface could directly map to a type class in Haskell. Is that thinking usually an anti-pattern.This problem I was solving is more of a re-implementation of some code I had in Python. In Python, I had a very class-based structure of this design. By class based structure, I mean we have class-level methods for each class (where each class is a type of Task), and all of them implement the same set of methods. This classes are never instantiated, but all methods are invoked on the class.WIth that perspective, the record patter @Patrick recommended directly maps to that design. The record data type here becomes a abstract-representation of my class(abstract base class in OO terms) and each task provides its methods. I see that relationship. Is that the approach I should be aiming for?On Tue, Feb 28, 2017 at 9:55 AM, Patrick Chilton <chpatrick@gmail.com> wrote:You could also consider representing tasks like this instead of using a typeclass:data Task = Task{ process :: m (), canRun :: m Bool}The Taskable + existential GADT example seems like it could be an example of the existential antipattern.If your GADT really does have a as a type parameter, it would be more idiomatic to check for the typeclass when you use it:doStuffWithTasks :: Taskable a => Task a -> ...But then what's the point of the Task datatype?On Tue, Feb 28, 2017 at 1:48 AM, Guru Devanla <gurudev.devanla@gmail.com> wrote:______________________________Hello All,to create an wrapper for these Taskables and create a functor for it as follows
I am working on a program that will define a bunch of tasks. Each task
will have to implement certain methods as part of a type class.
-- task 1
data UpdateAcctsTask = UpdateAccts
-- task 2
data EmailConfig = EmaiConfig {someattrs::String}
data SendEmailTask = SendEmailsTask EmailConfig
-- task 3
data GeneralWriterTask a = GeneralWriterTask a
Each of these tasks implement a class, Taskable. The return
values are simplified for this example.
class Taskable a where
process :: a -> Bool
can_run :: a -> Bool
This works fine. I can expand on these tasks and execute them.
Now, I wanted to be able to defined dependencies between these (Taskable's). I decided
I could create a data type for this dependency and may be also get a FreeMonad
around this structure for further processing using a graph of Tasks. But, before that I wantedAppreciate any help on this. Thank you!
The first thing I did was, define a Task, which generalizes over all
the above defined (and future Taskables)
data Task a where
Task :: (Taskable a) => a -> Task a
instance Functor Task where
fmap:: (Taskable a, Taskable b) -> (a -> b) -> Task a -> Task b --- THIS DOES NOT WORK
fmap f (Task a) = Task $ f a
But, I realized that I cannot define an fmap over a type constraint.
My questions are:
1. Is there any way to do this. I see there is an answer of SO. I wanted
to make sure if there were any improvements to this since that answer'
was posted.
http://stackoverflow.com/questions/17157579/functor-instance -for-a-gadt-with-type-constrai nt
2. Secondly, I would like to know why this is not possible. Is it a current
limitation of GHC or if there is some fundamental category theory concepts
that dis-allows such declarations that I need to grok!_________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-caf e
Only members subscribed via the mailman list are allowed to post.