haskell - How to create a list of heterogeneous datatypes without using sum-types or copies -


the use-case: app follow users across several messaging services. there's twitteraccount datatype, facebookaccount datatype, etc. these joined account sum-type, next level of hierarchy leads problem.

a twitteraccount has list of twitterposts, facebookaccount has list of facebookposts, etc.

my task: want able put posts last 10 days accounts single list, , extract common time , message body fields them display.

my failed approach: thought if every class of post implemented typeclass simplepost exposing functions messagebody , messagetime that might solve problem, can't create list of [simplemessage].

i want maintain invariant twitteraccount can containtwitterposts, , on, can't use sum-types. i'd prefer not create copies of objects this.

what best, cleanest, haskell-ish design problem?

update isn't answer, alternative 4 solutions provided recursion.ninja , helder pereira i've been thinking if can meet invariants using phantom types, , account , post types hold possible information required providers. use of tuples, , awkward logic, means doesn't scale well; perhaps should in different question.

{-# language emptydatadecls #-}     -- fsharpisms (|>) = flip ($) (<|) = ($) infixr 0 <|   data twitter data facebook data linkedin  data post = post{     postbody :: string,     postdate :: utctime,     postforwarded :: bool,     postfriendmentions :: [username]     } deriving (show, eq)  data account = account {     accountname  :: string,     accountposts :: [post a]     } deriving (show, eq)  data user = user {     username   :: string,     usertweets :: account twitter,     userfaces  :: account facebook,     userlinks  :: account linkedin     }  prettyshowutc :: utctime -> string prettyshowutc utc = ...  prettyshow :: post -> string prettyshow p = prettyshowutc (postdate p) ++ " : " ++ show (postbody p)  showorderedof2 :: ([post a], [post b]) -> [string] showorderedof2 ([], []) = [] showorderedof2 (ls, []) = map prettyshow ls showorderedof2 ([], rs) = map prettyshow rs showorderedof2 ((l:ls), (r:rs)) =      if postdate l < postdate r     prettyshow l : showorderedof2 (ls, (r:rs))     else prettyshow r : showorderedof2 ((l:ls), rs)  showorderedof3 :: ([post a], [post b], [post c]) -> [string] showorderedof3 ([], [], []) = [] showorderedof3 (as, [], []) = map postbody showorderedof3 ([], bs, []) = map postbody bs showorderedof3 ([], [], cs) = map postbody cs showorderedof3 (as, bs, []) = showorderedof2 (as, bs) showorderedof3 ([], bs, cs) = showorderedof2 (bs, cs) showorderedof3 (as, [], cs) = showorderedof2 (as, cs) showorderedof3 ((a:as), (b:bs), (c:cs)) =     let (adate, bdate, cdate) = (postdate a, postdate b, postdate c)         mindate = minimum [adate, bdate, cdate]     in     if adate == mindate     prettyshow : showorderedof3 (as, (b:bs), (c:cs))     else (if bdate == mindate          prettyshow b : showorderedof3 ((a:as), bs, (c:cs))          else prettyshow c : showorderedof3 ((a:as), (b:bs), cs))  createandshowsample :: io () createandshowsample =     let faceac = account {...} :: account facebook         twitac = account {...} :: account twitter         linkac = account {...} :: account linkedin     in      showorderedof3 (accountposts faceac, accountposts twitac, accountposts linkac)         |> intercalate "\n"         |> putstrln 

you should abstract facebookaccount , twitteraccount instances of socialmediaaccount

haskell code:

import control.applicative ((<$>)) import data.list import data.ord import data.time  data facebookaccount = facebookaccount [facebookpost] data twitteraccount  = twitteraccount  [twitterpost] data facebookpost    = facebookpost string utctime data twitterpost     = twitterpost  string utctime  data socialmediaaccount     = socialmediaaccount     { accountposts :: [socialmediapost]    } data socialmediapost     = socialmediapost    { postbody :: string    , posttime :: utctime    }  class socialmedia   simpleaccount  :: -> socialmediaaccount    instance socialmedia facebookaccount   simpleaccount (facebookaccount xs) = socialmediaaccount $ f <$> xs            f (facebookpost text time) = socialmediapost text time  instance socialmedia twitteraccount   simpleaccount (twitteraccount xs) = socialmediaaccount $ f <$> xs            f (twitterpost text time) = socialmediapost text time  getallmessages :: (socialmedia a, socialmedia b) => -> b -> [socialmediapost] getallmessages xs ys = sortby (comparing posttime)                       $ extract xs                     ++ extract ys       extract :: socialmedia => -> [socialmediapost]     extract = accountposts . simpleaccount 

Comments

Popular posts from this blog

php - Admin SDK -- get information about the group -

dns - How To Use Custom Nameserver On Free Cloudflare? -

Python Error - TypeError: input expected at most 1 arguments, got 3 -