Re: [Haskell-cafe] Store type-class polymorphic values generically

2013-10-11 Thread Christopher Done
 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

2013-10-04 Thread Heinrich Apfelmus

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

2013-10-04 Thread Christopher Done
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

2013-10-04 Thread Heinrich Apfelmus

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

2013-10-04 Thread Simon Peyton-Jones
| 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

2013-10-04 Thread Alp Mestanogullari
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

2013-10-03 Thread Christopher Done
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