haskell - Rebindable syntax for arrow with constraint -


consider free arrow task remember how constructed. , want put constraint (e.x. show) on arguments of arrow:

data freearrow b    leafarrow :: (show a, show b) => freearrow b    seqarrow :: (show a, show b, show c) => freearrow b -> freearrow b c -> freearrow c   pararrow :: (show a1, show b1, show a2, show b2) => freearrow a1 b1 -> freearrow a2 b2 -> freearrow (a1, a2) (b1, b2)  deriving instance show (freearrow b) 

to define arrow instance freearrow need define restricted versions of category , arrow:

class category cat     id :: show => cat a     (.) :: (show a, show b, show c) => cat b c -> cat b -> cat c  class category => arrow     arr :: (show b, show c) => (b -> c) -> b c     first :: (show b, show c, show d) => b c -> (b,d) (c,d)     second :: (show b, show c, show d) => b c -> (d,b) (d,c)     (***) :: (show b, show c, show b', show c') => b c -> b' c' ->      (&&&) :: (show b, show c, show c') => b c -> b c' -> b (c,c') 

there instances:

instance category freearrow    id = leafarrow   (.) = flip seqarrow  instance arrow freearrow    arr _ = leafarrow   first f = pararrow f id   second f = pararrow id f    (***) = pararrow 

the approach operates hand-written arrows:

myarrow :: freearrow double double myarrow = (a &&& a) >>> arr (uncurry (+))   :: freearrow double double         = leafarrow  main :: io () main = print myarrow 

will print:

seqarrow (seqarrow leafarrow (pararrow leafarrow leafarrow)) leafarrow 

but arrow syntax (ghc 7.8.3):

myarrow :: freearrow double double myarrow = proc v -> -< v   :: freearrow double double         = leafarrow  main :: io () main = print myarrow 

i got errors like:

/home/ncrashed/dev/haskell/arrowproblem.hs:54:11:     no instance (show c) arising use of ‘arr’     possible fix:       add (show c) context of         type expected context: (b -> c) -> freearrow b c     in expression: arr     when checking ‘arr’ (needed syntactic construct)       has required type: forall b1 c1. (b1 -> c1) -> freearrow b1 c1       arising proc expression       @ /home/ncrashed/dev/haskell/arrowproblem.hs:1:1     in expression: proc v -> -< v  /home/ncrashed/dev/haskell/arrowproblem.hs:54:11:     no instance (show c) arising use of ‘>>>’     possible fix:       add (show c) context of         type expected context:           freearrow b -> freearrow b c -> freearrow c     in expression: (>>>)     when checking ‘(>>>)’ (needed syntactic construct)       has required type: forall a1 b1 c1.                              freearrow a1 b1 -> freearrow b1 c1 -> freearrow a1 c1       arising proc expression       @ /home/ncrashed/dev/haskell/arrowproblem.hs:1:1     in expression: proc v -> -< v  /home/ncrashed/dev/haskell/arrowproblem.hs:54:11:     no instance (show d) arising use of ‘first’     possible fix:       add (show d) context of         type expected context:           freearrow b c -> freearrow (b, d) (c, d)     in expression: first     when checking ‘first’ (needed syntactic construct)       has required type: forall b1 c1 d1.                              freearrow b1 c1 -> freearrow (b1, d1) (c1, d1)       arising proc expression       @ /home/ncrashed/dev/haskell/arrowproblem.hs:1:1 

is there way fix this? bug?

perhaps should fall arrowp preprocessor...

p.s. there full sample of code

what problem is

when use haskell's arrow notation, not naively desugar proc v -> x -< y literal text arr (\v -> y) >>> x (using whatever arr , >>> in-scope) rather uses true values expecting, desugaring effectively:

control.arrow.arr (\v -> y) control.arrow.>>> x 

the problem precisely when ran problem -- let's pretend it's house closed doorway -- chose build own house right next door door open (defining own arrow , category instances), , you're trying drive remote-control car hopelessly stuck in other house, , you're confused because doorways similar, why isn't there rc car upstairs in this house commands seamlessly rerouted to? answer is, you'll need build own rc car , controller (haskell source-to-source converter) complete approach.

clearly easier way chuck of work , instead doorknob other house.

how fix code

let me summarize how walls , doors haskell type classes work. you're programming @ advanced enough level may review, apologize if brief. show type class, example, construct show dictionary-of-functions (show, showsprec, showlist) type constructor, , functions can use other functions coming other constraints on class's type-parameters.

the compiler stores show dictionary takes type constructor pair: first, list of constraints on type parameters, second, actual dictionary you've implemented, potentially using functions earlier constraints. when compiler resolves show (mytype parama paramb) therefore looks mytype in show dictionary, finds instance, verifies parama , paramb satisfy whatever constraints have satisfy (getting auxiliary dictionaries-of-functions classes), , forms dictionary of show functions. that's review; if not, go , study tutorial on how haskell type classes work.

this means don't need show in constructors you're writing. they're constructors! don't glue values in way can latter pattern-match apart -- don't need functions show or showsprec those. without them can still write:

data freearrow b     leafarrow :: freearrow b     seqarrow :: freearrow t -> freearrow t b -> freearrow b     pararrow :: freearrow a1 b1 -> freearrow a2 b2 -> freearrow (a1, a2) (b1, b2) deriving instance show (freearrow b)  instance category freearrow id = leafarrow; (.) = flip seqarrow  instance arrow freearrow     arr = const leafarrow     first = flip pararrow id     second = pararrow id     (***) = pararrow 

in fact can use show on arbitrary arrow,

*main> show (leafarrow :: freearrow () (io string)) "leafarrow" 

whereas code above not create value because leafarrow constructor demanded show instance io string, can't provide it. , intended code works easily:

*main> :set -xarrows *main> print $ proc v -> (leafarrow :: freearrow double double) -< v seqarrow leafarrow (seqarrow leafarrow leafarrow) 

we can of because "how constructed" information not use show x typeclass define show x instance of instances.

how think trying do

the reason can "fix" stuff above you're not introspecting deep parameters involved -- think want out of show type class. in fact need define wholly different type class sort of type information available haskell runtime (unless i'm totally mistaken):

class typeof t     -- integer here 10 type-constructor application, otherwise     -- precedence of enclosing type-construction-operator.     typeprec :: int -> t -> string -> string     typeprec _ t = (typeof t ++)     typeof :: t -> string     typeof t = typeprec 0 t "" -- starts @ 0 if have no other info.  instance typeof int typeof _ = "int"  instance (typeof x) => typeof [x]     typeof list = "[" ++ typeof (head list) ++ "]" instance (typeof x, typeof y) => typeof (x, y)     typeof x = "(" ++ typeof (fst x) ++ ", " ++ typeof (snd x) ++ ")"  -- helper functions precedence parsing: arg f x = typeprec 10 (f x) pif m n expr | m <= n    = ('(' :) . expr . (')' :)              | otherwise = expr <**> b = . (' ' :) . b infixr 1 <**>  instance (typeof x) => typeof (io x)     typeprec n x = pif 10 n $ ("io" ++) <**> arg io x         io = undefined :: io x -> x  instance (typeof x, typeof y) => typeof (either x y)     typeprec n x = pif 10 n $ ("either" ++) <**> arg left x <**> arg right x         left  = undefined :: either x y -> x               right = undefined :: either x y -> y 

first, there may way write c-based extension haskell instead provides typeof :: x -> string x haskell; hypothetically adding string parameter arrows. let's skip possibility.

the biggest problem above (.) control.category, explicitly forbids access internal type b when composing cat b cat b c. overcoming going difficult. can't thread phantom-type data through cat unless can protect cat changing types.

a secondary problem you're trying annotate existing arrow metadata rather defining own arrow probe structure. along lines might crazy pathway:

prelude control.arrow control.monad.free control.monad.identity> :set prompt "ghci> " ghci> type myarrow = kleisli identity ghci> let x = arr (3*) :: kleisli (free (arrowmonad myarrow)) int int ghci> :t x x :: kleisli (free (arrowmonad myarrow)) int int 

basically we're looking here use typeof somehow "walk" tree here embodied free monad.

there obvious restrictions preventing saying "this arrow if both input , output implement typeof" (namely, arr not have needed typeof constraint), types can't hidden string in constructor; can't hidden in phantom type because says cat b c -> cat b -> cat c, 2 obvious ways store intermediary types). there not, far can see, obvious restriction having class which, @ end of constructing our values, built of things simultaneously implement arrow , typeof.


Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -