Re: [Haskell-cafe] Store type-class polymorphic values generically
Wait... what do you mean Core cannot generate new names to be exported. I meant if I add a new name in the Core transformation, that doesn't change the module's export list as seen by everything outside that module. Which makes sense, it just means I have to change my approach. Maybe you mean that you want your plugin to transform module M( f ) where f = e into module M( f_ ) where f_ = ...f... f = e No, I meant that module M(f) where f = e should be come module M (f, f_) where f = readRefOf f_; f_ = makeSomeRef e In other words, the API is only changed in that an additional binding has been exported for each top-level definition to which you can write (only of the correct type) a new definition. This is something that you could do manually, write it by hand, but I want it automatic for any module I load into GHCi! That seems pretty drastic, because now the programmer's API for the module has changed. Are you sure you don't want to do this module M( f ) wehre f_ = e f = ...f_... by renaming the existing f with some local name. Sure -- but both need to be exported otherwise you can't update the definition of `f` by writing to `f_`. With both, all other modules (and the module itself) just refer to `f' as they normally would, it's just that `f` gets its definition from some kind of mutable cell. I discussed with Daniel Peebles an approach to this with the new kind polymorphic Typeable landing in GHC 7.8, in which I could safely write functions in and out with Fun from HList: http://code.haskell.org/~aavogt/HList/docs/HList/Data-HList-FakePrelude.html#t:Fun Hypothetically I can use bog standard Typeable deriving for that type, and actually use Data.Dynamic to store all functions, using fromDynamic :: a - Maybe safe coercion. Don't get me wrong, I don't want the plugin to break any APIs or do anything unsafe (beyond using unsafePerformIO to hold a Map Name Dynamic or so), I just want in-place update of IO-ish actions. I'm compiling GHC from Git at the moment to see if this approach is worthwhile. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Store type-class polymorphic values generically
Christopher Done wrote: It's very easy to state this problem without enough details and mislead people into providing a solution for a different problem, so I'll try to include all the information and use-case. I need a function that can store a value in a concrete opaque type. I know the type of the value when I store it, and I know the type of the value when I extract it, insofar as I know the type inclusive of a class constraint context. But the container must store many different things at once. Given that I know the type of the thing when I store it and when I extract it, there ought to be a “safe’ way to do this, in the same way that Data.Dynamic is “safe”. [..] I have to ashamedly admit that I didn't read your problem description in its entirety, but maybe my vault package can help? http://hackage.haskell.org/package/vault In particular, the Locker stores arbitrary values like Dynamic , except that values are extracted and removed with the help of a Key . This gets rid of the Typeable constraint. Note that there is a fundamental problem with storing polymorphic types, which is related to the value restriction for reference types. One of the main points of the Typable class is actually that it enforces monomorphic types. Similarly, the vault library enforces monomorphic types by having newKey in the IO monad. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Store type-class polymorphic values generically
On 4 October 2013 10:56, Heinrich Apfelmus apfel...@quantentunnel.de wrote: In particular, the Locker stores arbitrary values like Dynamic , except that values are extracted and removed with the help of a Key . This gets rid of the Typeable constraint. lock :: Key a - a - Locker I can't pass anything with class constraints to that. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Store type-class polymorphic values generically
Christopher Done wrote: On 4 October 2013 10:56, Heinrich Apfelmus apfel...@quantentunnel.de wrote: In particular, the Locker stores arbitrary values like Dynamic , except that values are extracted and removed with the help of a Key . This gets rid of the Typeable constraint. lock :: Key a - a - Locker I can't pass anything with class constraints to that. I don't know what something with a class constraint means. But I guess you want to pass a value with a *polymorphic* type? This is no problem, but requires impredicative polymorphism: a = (forall b. Show b = b - IO ()) lock :: Key (forall b. Show b = b - IO ()) - (forall b. Show b = b - IO ()) - Locker Unfortunately, GHC's support for that is a little shaky, but a solution that always works is to put it in a new data type. data Dummy = Dummy { unDummy :: forall b. Show b = b - IO () } lock :: Key Dummy - Dummy - Locker It seems to me that your problem decomposes into two problems: 1. A heterogenous store for values of different types. 2. Values with polymorphic instead of monomorphic types. Solution for problem 1 are usually restricted to monomorphic types, but you can work around it. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Store type-class polymorphic values generically
| However, I want to write this as a core-to-core | translation as a ghc-plugin. I want the definition go = putStrLn Hello | World! to be translated to what I wrote above. Core cannot generate new | names to be exported from a module, so go_ is now gone. Wait... what do you mean Core cannot generate new names to be exported. I think a core-to-core plugin can certainly generate new top-level function definitions. Maybe you mean that you want your plugin to transform module M( f ) where f = e into module M( f_ ) where f_ = ...f... f = e That seems pretty drastic, because now the programmer's API for the module has changed. Are you sure you don't want to do this module M( f ) wehre f_ = e f = ...f_... by renaming the existing f with some local name. I don't like all this unsafe hackery! Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Store type-class polymorphic values generically
Hi Chris, Maybe this package (from Edward Kmett, surprisingly) could help: http://hackage.haskell.org/package/constraints-0.3.3/docs/Data-Constraint.html? Considering it kind of reifies the type class constraints, I'm wondering whether you could use this to carry the constraints along the value you're storing? I haven't given it a lot of thoughts for now, but maybe you can get something decent working with this? On Fri, Oct 4, 2013 at 12:41 PM, Heinrich Apfelmus apfel...@quantentunnel.de wrote: Christopher Done wrote: On 4 October 2013 10:56, Heinrich Apfelmus apfel...@quantentunnel.de wrote: In particular, the Locker stores arbitrary values like Dynamic , except that values are extracted and removed with the help of a Key . This gets rid of the Typeable constraint. lock :: Key a - a - Locker I can't pass anything with class constraints to that. I don't know what something with a class constraint means. But I guess you want to pass a value with a *polymorphic* type? This is no problem, but requires impredicative polymorphism: a = (forall b. Show b = b - IO ()) lock :: Key (forall b. Show b = b - IO ()) - (forall b. Show b = b - IO ()) - Locker Unfortunately, GHC's support for that is a little shaky, but a solution that always works is to put it in a new data type. data Dummy = Dummy { unDummy :: forall b. Show b = b - IO () } lock :: Key Dummy - Dummy - Locker It seems to me that your problem decomposes into two problems: 1. A heterogenous store for values of different types. 2. Values with polymorphic instead of monomorphic types. Solution for problem 1 are usually restricted to monomorphic types, but you can work around it. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com __**_ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe -- Alp Mestanogullari ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Store type-class polymorphic values generically
It's very easy to state this problem without enough details and mislead people into providing a solution for a different problem, so I'll try to include all the information and use-case. I need a function that can store a value in a concrete opaque type. I know the type of the value when I store it, and I know the type of the value when I extract it, insofar as I know the type inclusive of a class constraint context. But the container must store many different things at once. Given that I know the type of the thing when I store it and when I extract it, there ought to be a “safe’ way to do this, in the same way that Data.Dynamic is “safe”. The use-case is I want to store a table of IO-like actions in an opaque like [(Name,Dynamic)] and I write into it statically, e.g. in GHCi. The reason is due to this approach: go_ref = newIORef go_ go_ = putStrLn Hello, World! go = do go' - liftIO $ readIORef go_ref go' main = forkIO $ forever $ go then in GHCi I writeIORef go_ (putStrLn What's up?) then go will now start printing What's up? This works now, I can do this presently. However, I want to write this as a core-to-core translation as a ghc-plugin. I want the definition go = putStrLn Hello World! to be translated to what I wrote above. Core cannot generate new names to be exported from a module, so go_ is now gone. So how does the `go' function read and write the IORef? With a table: table = unsafePerformIO $ newIORef [(go,Dynamic go_ref)] Hurrah! I can now put table in some module like DynamicUpdate.table and then read/write to it from Core in the generated definition of go. Done. But how do I update it from the GHCi REPL? What follows is where I'm stuck. So with Data.Dynamic, I have: toDyn :: Typeable a = a - Dynamic With toDyn I can store concrete values and functions and then extract them: λ fmap ($ 12) (fromDynamic (toDyn ((*2) :: Int - Int)) :: Maybe (Int - Int)) Just 24 But the problem with toDyn is that it can only store concrete values due to the Typeable constraint. So then I turn to existentials and unsafeCoerce: λ data Anything = forall a. Anything a λ let x = Anything id λ case x of Anything (unsafeCoerce - (id' :: Int - Int)) - id' 123 123 Great, I was able to store a value which contained non-concrete types. But now consider the case of a value with type-class polymorphic type in it: y = Anything (print :: Show a = a - IO ()) Which cannot be type checked, because the Show instance is ambiguous. So you might propose to use rank-N types, like this: data Anything = Anything (Show a = a - IO ()) Now I can store print in there happily. But now the type is not Anything, it's not generic anymore. Maybe I want to store `print', maybe I want to store `readLn'. Dead end. I don't want to have to generate existential wrappers for all functions I might possibly want to store. The support of Constraints in this page http://blog.omega-prime.co.uk/?p=127 makes me think that it's still possible. It would be cool to somehow store a tuple of the dictionary of the constraint and the value itself and then I'd later be able to extract it. But I'm finding it difficult developing anything even simple. Any ideas/help appreciated! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe