<div dir="ltr"><div><div><div>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.  <br><br></div>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?<br><br></div>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.<br><br></div>The <a href="https://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/" target="_blank">existential antipattern</a>. link was very useful and made me re-asses my inclination to defining type classes and embedded types right away.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Feb 28, 2017 at 9:55 AM, Patrick Chilton <span dir="ltr"><<a href="mailto:chpatrick@gmail.com" target="_blank">chpatrick@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>You could also consider representing tasks like this instead of using a typeclass:</div><div><br></div><div>data Task = Task</div><div>  { process :: m ()</div><div>  , canRun :: m Bool</div><div>  }</div><div><br></div><div>The Taskable + existential GADT example seems like it could be an example of the <a href="https://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/" target="_blank">existential antipattern</a>.</div><div><br></div><div>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:</div><div><br></div><div>doStuffWithTasks :: Taskable a => Task a -> ...</div><div><br></div><div>But then what's the point of the Task datatype?</div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Feb 28, 2017 at 1:48 AM, Guru Devanla <span dir="ltr"><<a href="mailto:gurudev.devanla@gmail.com" target="_blank">gurudev.devanla@gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><div>Hello All,<br><br>I am working on a program that will define a bunch of tasks. Each task<br>will have to implement certain methods as part of a type class.<br><br>-- task 1<br>data UpdateAcctsTask = UpdateAccts<br><br>-- task 2<br>data EmailConfig = EmaiConfig {someattrs::String}<br>data SendEmailTask = SendEmailsTask EmailConfig<br><br>-- task 3<br>data GeneralWriterTask a = GeneralWriterTask a<br><br>Each of these tasks implement a class, Taskable. The return<br>values are simplified for this example.<br><br>class Taskable a where<br>  process :: a -> Bool<br>  can_run :: a -> Bool<br><br><br>This works fine. I can expand on these tasks and execute them.<br><br>Now, I wanted to be able to defined dependencies between these (Taskable's). I decided<br>I could create a data type for this dependency and may be also get a FreeMonad<br>around this structure for further processing using a graph of Tasks. But, before that I wanted<br></div>to create an wrapper for these Taskables and create a functor for it as follows<br><div><br>The first thing I did was, define a Task, which generalizes over all<br>the above defined (and future Taskables)<br><br>data Task a where<br>  Task :: (Taskable a) => a -> Task a<br><br><br>instance Functor Task where<br>  fmap:: (Taskable a, Taskable b) -> (a -> b) -> Task a  -> Task b    --- THIS DOES NOT WORK<br>  fmap f (Task a) = Task $ f a<br><br><br>But, I realized that I cannot define an fmap over a type constraint.<br><br>My questions are:<br><br>1. Is there any way to do this. I see there is an answer of SO. I wanted<br>   to make sure if there were any improvements to this since that answer'<br>   was posted. <br>   <a href="http://stackoverflow.com/questions/17157579/functor-instance-for-a-gadt-with-type-constraint" target="_blank">http://stackoverflow.com/quest<wbr>ions/17157579/functor-instance<wbr>-for-a-gadt-with-type-constrai<wbr>nt</a><br><br>2. Secondly, I would like to know why this is not possible. Is it a current<br>   limitation of GHC or if there is some fundamental category theory concepts<br>   that dis-allows such declarations that I need to grok!<br><br></div>Appreciate any help on this. Thank you!<br></div>
<br></div></div><span class="">______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bi<wbr>n/mailman/listinfo/haskell-caf<wbr>e</a><br>
Only members subscribed via the mailman list are allowed to post.<br></span></blockquote></div><br></div>
</blockquote></div><br></div>