functional programming - Is there a way in Haskell to express a point free function to edit the property of a data type? -
i have type:
data cons = cons {myprop :: string}
and later on i'm mapping on list, setting property different value:
fmap (\x -> x{myprop = ""}) mylist
is there point free way express anonymous function?
there isn't point free way of doing this, can instead use lens library (which comes whole basket of goodies):
{-# language templatehaskell #-} import control.lens -- if put _ @ beginning of field name lens can derive methods data cons = cons { _myprop :: string } deriving (eq, show) -- derives myprop lens (works fields in record) makelenses ''cons -- can manually -- myprop :: functor f => (string -> f string) -> cons -> f cons -- myprop = lens _myprop (\c newprop -> c { _myprop = newprop }) -- lets define lenses type without depending on lens -- bigger deal might think. can support library , -- , paradigms without depending on @ all. main = let cs = map cons ["a", "b", "c"] -- prefix set function test1 = fmap (set myprop "") cs -- or operator test2 = fmap (myprop .~ "") cs print cs print test1 print test2
that "basket of goodies" comes lenses contains things like
data email = email { _emailaccount :: string , _emaildomain :: string } deriving (eq, show) makelenses ''email data person = person { _personname :: string , _personage :: int , _personemail :: email } deriving (eq, show) makelenses ''person testpeople :: [person] testpeople = [ person "a" 40 (email "aaa" "gmail.com"), person "b" 45 (email "bbb" "email.com"), person "c" 50 (email "ccc" "outlook.com")] domains :: [person] -> [string] domains ps = ps^..traverse.personemail.emaildomain statefulfun :: monadio m => statet person m () statefulfun = liftio $ putstrln "changing name" personname .= "a different name" liftio $ putstrln "the name changed!" personemail.emailaccount %= map toupper morestate :: monadio m => statet person m () morestate = personname .= "foo" zoom personemail $ current <- liftio $ putstr "current email is: " liftio $ print current emailaccount .= "foo" emaildomain .= "foo.com" main :: io () main = finalstate <- execstatet (morestate >> statefulfun) (head testpeople) print finalstate
as can see, lenses compose backwards (they don't, it's because have more general type lets them crazy things). there's nice ways of traversing complex data structures, optionally performing effects go, , plenty of operators writing imperative looking stateful code appears normal oop method access dot. lets abstract common , complex patterns on large , complex data structures little effort, once start grok them @ least!
Comments
Post a Comment