haskell hlist hnil pattern matching hfoldl -


i've been trying code work data.hlist. know can need adt alone wanted see how work hlist experimenting. i'm having trouble compiling code wrote.

{-# language gadts #-}  module testhlist  import data.hlist.commonmain  data mytype1 = mytype1 { x::int, y::int } deriving (show) data mytype2 = mytype2 { text::string, slen::int } deriving (show) data mytype3 = mytype3 { dval1::int, dval2::string } deriving (show)  test1 = hcons (mytype2 { text = "hello", slen=5 })           (hcons (mytype1 { x=1, y=2 })           (hcons (mytype3 { dval1=3, dval2="world" })           hnil))  test2 = hcons (mytype1 { x=4, y=5 })           (hcons (mytype1 { x=6, y=7 })           (hcons (mytype2 { text="again.", slen=6 })           hnil))  addtype1 ls1 ls2 = happendlist ls1 ls2   class mytypesint   sumit :: -> int  instance mytypesint mytype1   sumit val = (x val) + (y val)  instance mytypesint mytype2   sumit val = slen val  instance mytypesint mytype3   sumit val = (dval1 val) * 2  sumtest1 v = sumit v sumtest2 ls = sumit (hhead ls)  foldtest ls = hfoldl (\(v1,v2) -> v1 + (sumit v2)) 0 ls sumtest3 = foldtest test1  sumall hnil = 0 sumall ls = (sumit (hhead ls)) + (sumall (htail ls))  {- sumall3 xs   | xs == hnil = 0   | otherwise = (sumit (hhead xs)) + (sumall3 (htail xs)) -} 

the code doesn't useful it's intended me understand how use hlist. code declares 3 separate data types , makes class , defines instances 3 types. goal setup list , execute class function, sumit, on each element of list based on instance defined them. know test1, test2 addtype1, sumtest1 , sumtest2 work. compile errors foldtest , sumall functions. think need define function declarations not sure how. here compile errors.

testhlist.hs:39:1: not deduce (mytypesint a0)   arising ambiguity check `foldtest' context (num z,                   hfoldl ((int, a) -> int) z xs r,                   mytypesint a)   bound inferred type `foldtest':              (num z, hfoldl ((int, a) -> int) z xs r, mytypesint a) =>              hlist xs -> r   @ testhlist.hs:39:1-55 type variable `a0' ambiguous possible fix: add type signature fixes these type variable(s) note: there several potential instances:   instance mytypesint mytype3 -- defined @ testhlist.hs:33:10   instance mytypesint mytype2 -- defined @ testhlist.hs:30:10   instance mytypesint mytype1 -- defined @ testhlist.hs:27:10 when checking `foldtest'   has inferred type `forall z (xs :: [*]) r a.                          (num z, hfoldl ((int, a) -> int) z xs r, mytypesint a) =>                          hlist xs -> r' probable cause: inferred type ambiguous  testhlist.hs:42:8: couldn't match type `(':) * e0 l0' '[] * inaccessible code in   pattern constructor     hnil :: hlist ('[] *),   in equation `sumall' in pattern: hnil in equation `sumall': sumall hnil = 0  testhlist.hs:43:49: occurs check: cannot construct infinite type: l0 = (':) * e0 l0 expected type: hlist ((':) * e0 ((':) * e0 l0))   actual type: hlist ((':) * e0 l0) in first argument of `htail', namely `ls' in first argument of `sumall', namely `(htail ls)' in second argument of `(+)', namely `(sumall (htail ls))' 

my question know need fix code work? i've done quite few searches find answer. it's possible i've seen answer during search i'm not understanding it.

thanks

update:

while researching ideas in answers given ran across link: http://en.wikibooks.org/wiki/haskell/existentially_quantified_types

after reading easy implement trying do. i'm not changing answer. question how code work data.hlist , answers provided well. intention figure out how setup , use heterogeneous list , thought @ time data.hlist way it. following code bit easier me follow, wanted provide in case else finds useful.

{-# language existentialquantification #-}  module testheterlist  data mytype1 = mytype1 { x::int, y::int } deriving (show) data mytype2 = mytype2 { text::string, slen::int } deriving (show) data mytype3 = mytype3 { dval1::int, dval2::string } deriving (show)  class mytypesint   sumit :: -> int  instance mytypesint mytype1   sumit val = (x val) + (y val)  instance mytypesint mytype2   sumit val = slen val  instance mytypesint mytype3   sumit val = (dval1 val) * 2  data genelem = forall s. (show s, mytypesint s) => ge s instance show genelem   show (ge s) = show s  test1 :: [genelem] test1 = [ge (mytype2 { text = "hello", slen=5 }), ge (mytype1 { x=1, y=2 }), ge (mytype3 { dval1=3, dval2="world" })]  foldtest xs = foldl (\acc (ge val) -> acc + sumit val) (0::int) xs sumtest1 = foldtest test1  sumall [] = 0 sumall (ge v : xs) = (sumit v) + (sumall xs)  sumtest2 = sumall test1 

here's how can make hfoldl-based variant work:

data hsumall = hsumall instance (mytypesint a, int ~ int) => applyab hsumall (int, a) int   applyab hsumall (v1, v2) = v1 + sumit v2   foldtest ls = hfoldl hsumall (0 :: int) ls sumtest3 = foldtest test1 

making direct version work more tricky. first of all, have use pattern matching, because hlist gadt, , type refinement can't possibly work if use selector functions. furthermore, functions matching on gadts need explicit type signatures. end this:

sumall :: hlist ls -> int -- wrong sumall hnil         = 0 sumall (hcons x xs) = sumit x + sumall xs 

this produces following type error:

could not deduce (mytypesint e) arising use of `sumit' context (ls ~ (':) * e l1) ...

and ghc of course right complain. need all types in ls instance of mytypesint. i've browsed hlist package see if library provides way express this, seems me doesn't. fortunately, relatively easy these days (requires constraintkinds , importing ghc.exts access constraint):

type family (c :: * -> constraint) (xs :: [*]) :: constraint type instance c '[]       = () type instance c (x ': xs) = (c x, c xs) 

then can say:

sumall :: mytypesint ls => hlist ls -> int sumall hnil         = 0 sumall (hcons x xs) = sumit x + sumall xs 

this typechecks , works expected.


Comments

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -