Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-25 Thread Maxime Henrion
On Sat, 2012-02-25 at 11:38 +0100, José Pedro Magalhães wrote:
 2012/2/25 Andres Löh andres.l...@googlemail.com
  Would you have an example of a type for which it would be
 useful to have
  a DeepSeq instance, and that would require a V1 instance? I
 cannot think
  of one now; I originaly thought it would be necessary to
 permit deriving
  DeepSeq instances for types tagged with void types, but as
 José
  explained, in that case, the V1 instance isn't needed
 because those void
  types don't show up in the representation.
 
 
 While void datatypes are rare, it just doesn't make sense to
 exclude
 them. It's an arbitrary restriction. Here's a constructed
 example:
 
 data X a = C1 Int | C2 a
 data Z -- empty
 
 type Example = X Z
 
 We're using Z as a parameter to X in order to exclude the use
 of the
 C2 case. Without a V1 case, you cannot use deepSeq on values
 of type
 Example.
 
 Yes, I agree. There should be a V1 instance, and it should return
 `undefined`. This gives the expected behavior of `seq` on an empty
 datatype, I think. If there is no V1 instance, you'll get a
 type-checking error (no instance for V1), preventing generic deepseq
 on any datatype that happens to use an empty datatype in its
 definition.

Thanks for all the input guys. I have just released generic-deepseq
2.0.1.0 to hackage, with fixed U1 and V1 instances per this discussion.

Cheers,
Maxime



signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-24 Thread Maxime Henrion
On Fri, 2012-02-24 at 07:49 +0100, Jos Pedro Magalhes wrote:
 Hi,
 
 2012/2/23 Maxime Henrion mhenr...@gmail.com
 
  * Why do you have the instance:
 
  instance GDeepSeq V1 where grnf _ = ()
 
  The only way to construct values of a void type is using ⊥.
 And I
  would expect that rnf ⊥ = ⊥, not (). I think the best thing
 is to just
  remove the V1 instance.
 
 
 This would have the consequence that any type tagged with a
 phantom type
 (for whatever reason) couldn't be used with deepseq, it would
 return
 bottom. What if I want to deepseq a 2-3 finger tree tagged
 with a
 type-level natural that ensures the proper shape of the tree
 statically?
 It seemed to me that I should be able to do that; this is why
 I added
 this V1 instance.
 
 I'm not sure I understand your comment... V1 should only be used for
 datatypes without constructors, such as `data Empty`.

Yes, such as the usual type-level naturals (not using DataKinds):

data Z
data S n

Those can be used to tag a type which also contains actual values that
you would want to deepseq? For example, a length-type vector? I seemed
to remember a similar construct for 2-3 finger trees that would
statically guarantee that the shape of the tree is valid, so I took that
as an example, but I don't remember the specifics.

Cheers,
Maxime
 
 



signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-24 Thread Maxime Henrion
On Fri, 2012-02-24 at 09:32 +0100, Jos Pedro Magalhes wrote:
 
 
 2012/2/24 Maxime Henrion mhenr...@gmail.com
 On Fri, 2012-02-24 at 07:49 +0100, Jos Pedro Magalhes wrote:
  Hi,
 
  2012/2/23 Maxime Henrion mhenr...@gmail.com
 
   * Why do you have the instance:
  
   instance GDeepSeq V1 where grnf _ = ()
  
   The only way to construct values of a void type is
 using ⊥.
  And I
   would expect that rnf ⊥ = ⊥, not (). I think the
 best thing
  is to just
   remove the V1 instance.
 
 
  This would have the consequence that any type tagged
 with a
  phantom type
  (for whatever reason) couldn't be used with deepseq,
 it would
  return
  bottom. What if I want to deepseq a 2-3 finger tree
 tagged
  with a
  type-level natural that ensures the proper shape of
 the tree
  statically?
  It seemed to me that I should be able to do that;
 this is why
  I added
  this V1 instance.
 
  I'm not sure I understand your comment... V1 should only be
 used for
  datatypes without constructors, such as `data Empty`.
 
 
 Yes, such as the usual type-level naturals (not using
 DataKinds):
 
 data Z
 data S n
 
 Those can be used to tag a type which also contains actual
 values that
 you would want to deepseq? For example, a length-type vector?
 
 But in those cases they are used as tags, not as values, and hence do
 not show up in the generic representation. So if all you want is to be
 able to deepseq a value of a type like
 
 data Proxy t = Proxy
 
 even if your value is of type `Proxy Ze`, you shouldn't need a `V1`
 instance.

Oh, ok; in that case, I probably don't need that V1 instance indeed. I
should probably write QuickCheck tests using the ChasingBottoms package
in order to ensure correct behaviour of this code.

Thanks,
Maxime



signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-24 Thread Maxime Henrion
On Fri, 2012-02-24 at 15:28 +0100, Andres Löh wrote:
 Hi.
 
  I don't understand what's going on here. Instances for V1 should of
  course be defined if they can be! And in this case, a V1 instance
  makes sense and should be defined. The definition itself doesn't
  matter, as it'll never be executed.
 
 
  The definition certainly matters:
 
 [...]
 
 You're right. I was too quick to conclude the definition doesn't
 matter. But it should still be there. V1 can occur in representations
 of non-empty types (even if the current mechanism might not generate
 them). You'd still want to be able to call generic functions on such
 types.

Would you have an example of a type for which it would be useful to have
a DeepSeq instance, and that would require a V1 instance? I cannot think
of one now; I originaly thought it would be necessary to permit deriving
DeepSeq instances for types tagged with void types, but as José
explained, in that case, the V1 instance isn't needed because those void
types don't show up in the representation.

Cheers,
Maxime


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-24 Thread Maxime Henrion
On Thu, 2012-02-23 at 23:24 +0100, Bas van Dijk wrote:
 Some nitpicking:
 
 * In the instance:
 
 instance GDeepSeq U1 where grnf _ = ()
 
 I think it makes sense to pattern match on the U1 constructor, as in:
 grnf U1 = ().
 
 I haven't checked if that's necessary but my fear is that assuming:
 data Unit = Unit deriving Generic; instance DeepSeq Unit
 rnf (⊥ :: Unit) would equal: () while I would expect it to equal ⊥.

I just tested this and you were right; I have corrected the code in the
mercurial repository.

 * Why do you have the instance:
 
 instance GDeepSeq V1 where grnf _ = ()
 
 The only way to construct values of a void type is using ⊥. And I
 would expect that rnf ⊥ = ⊥, not (). I think the best thing is to just
 remove the V1 instance.

I have confirmed what Jos explained, and V1 instances are indeed not
necessary for the use case I originally intended them for, that is for
types tagged with void types. I have removed the V1 instance for now.

Thanks,
Maxime


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-23 Thread Maxime Henrion
On Thu, 2012-02-23 at 23:24 +0100, Bas van Dijk wrote:
 On 23 February 2012 22:09, Maxime Henrion mhenr...@gmail.com wrote:
  On Sun, 2012-02-19 at 21:06 +0100, Bas van Dijk wrote:
  On 19 February 2012 18:11, Maxime Henrion mhenr...@gmail.com wrote:
   I'm guilty of not having preserved the rnf :: a - ()
   function as the class function though, it's a wrapper around deepseq
   in my code. I just didn't see the point of having a class function with
   such a signature versus having a function just like seq :: a - b -
   b. In retrospect, that might have been a bad idea, and maybe I should
   switch to have an rnf :: a - () class function to make switching even
   easier?
 
  I'm not sure but maybe a method like rnf :: a - () is easier to 
  optimize.
 
  Also in my experience (with generics support in aeson and cereal) it's
  a very good idea (performance-wise) to INLINE your methods like I did
  in my previous message. Of course the only way to know for sure is the
  create some (criterion) benchmarks.
 
  Well I wrote some dumb criterion benchmarks that run deepseq over
  increasingly bigger lists of numbers, and it appears that using rnf as
  the member function of the DeepSeq class indeed makes a _huge_
  difference.
 
 Nice, that's what I expected. Have you checked if adding INLINE
 pragma's helps even more? (I guess not since it's already on par with
 manual written code, as you mentioned)

Oh, I had forgotten to mention that: INLINE pragmas indeed didn't make
any significant difference in my tests, so I let them out.

 BTW I would also recommend making a benchmark for a big sum type.

Yes, I should definitely do that.

 Some nitpicking:
 
 * In the instance:
 
 instance GDeepSeq U1 where grnf _ = ()
 
 I think it makes sense to pattern match on the U1 constructor, as in:
 grnf U1 = ().
 
 I haven't checked if that's necessary but my fear is that assuming:
 data Unit = Unit deriving Generic; instance DeepSeq Unit
 rnf (⊥ :: Unit) would equal: () while I would expect it to equal ⊥.

That's a good point, I will do tests to see whether this makes a
difference. This seems to mirror my thinking when I asked you whether it
would be safe to skip seq calls in the case the constructor of a type is
strict in another e-mail (have you seen it?).

 * Why do you have the instance:
 
 instance GDeepSeq V1 where grnf _ = ()
 
 The only way to construct values of a void type is using ⊥. And I
 would expect that rnf ⊥ = ⊥, not (). I think the best thing is to just
 remove the V1 instance.

This would have the consequence that any type tagged with a phantom type
(for whatever reason) couldn't be used with deepseq, it would return
bottom. What if I want to deepseq a 2-3 finger tree tagged with a
type-level natural that ensures the proper shape of the tree statically?
It seemed to me that I should be able to do that; this is why I added
this V1 instance.

Cheers,
Maxime


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-23 Thread Maxime Henrion
On Thu, 2012-02-23 at 23:45 +0100, Maxime Henrion wrote:
 On Thu, 2012-02-23 at 23:24 +0100, Bas van Dijk wrote:
  * Why do you have the instance:
  
  instance GDeepSeq V1 where grnf _ = ()
  
  The only way to construct values of a void type is using ⊥. And I
  would expect that rnf ⊥ = ⊥, not (). I think the best thing is to just
  remove the V1 instance.
 
 This would have the consequence that any type tagged with a phantom type
 (for whatever reason) couldn't be used with deepseq, it would return
 bottom. 

Sorry, I had myself confused; it wouldn't return bottom, there would
just be no way to get an instance for it (the rest of the argument still
holds).


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-19 Thread Maxime Henrion
Hello all,


Yesterday I uploaded a new package on Hackage called generic-deepseq. It
implements the 'deepseq' function generically using the new GHC.Generics
framework as found in GHC = 7.2. It can be used as a replacement for
the deepseq package.

Given that hackage is currently down, here is an URL from a mirror where
the package description  documentation can be found:
 
http://hackage.factisresearch.com/package/generic-deepseq-1.0.0.0

Any suggestions are welcome.

Cheers,
Maxime Henrion


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-19 Thread Maxime Henrion
On Sun, 2012-02-19 at 16:17 +0100, Bas van Dijk wrote:
 On 19 February 2012 13:12, Maxime Henrion mhenr...@gmail.com wrote:
  Any suggestions are welcome.
 
 Nice work but it would be nice to have this functionality directly in
 the deepseq package as in:
 
 #ifdef GENERICS
 {-# LANGUAGE DefaultSignatures, TypeOperators, FlexibleContexts #-}
 #endif
 
 class NFData a where
 rnf :: a - ()
 rnf a = a `seq` ()
 
 #ifdef GENERICS
 default rnf :: (Generic a, GNFData (Rep a)) = a - ()
 rnf = grnf . from
 
 class GNFData f where
 grnf :: f a - ()
 
 instance GNFData U1 where
 grnf U1 = ()
 {-# INLINE grnf #-}
 
 instance NFData a = GNFData (K1 i a) where
 grnf = rnf . unK1
 {-# INLINE grnf #-}
 
 instance GNFData f = GNFData (M1 i c f) where
 grnf = grnf . unM1
 {-# INLINE grnf #-}
 
 instance (GNFData f, GNFData g) = GNFData (f :+: g) where
 grnf (L1 x) = grnf x
 grnf (R1 x) = grnf x
 {-# INLINE grnf #-}
 
 instance (GNFData f, GNFData g) = GNFData (f :*: g) where
 grnf (x :*: y) = grnf x `seq` grnf y
 {-# INLINE grnf #-}
 #endif
 
 Unfortunately this is not possible since the two default
 implementations conflict. I see two solutions:
 
 1) Change the DefaultSignatures extension to always give preference to
 the default signature. I think giving preference to the default
 signature makes sense since it's usually more specific (more
 constraint) and thus more correct than the default implementation.
 
 2) Remove the default implementation of rnf. I understand the default
 implementation gives some convenience when writing instances for types
 that have an all strict representation, as in:
 
 instance NFData Int
 instance NFData Word
 instance NFData Integer
 ...
 
 However, I think having the default implementation can mask some bugs as in:
 data T = C Int; instance NFData T
 which will neither give a compile time error nor warning.
 
 I don't think it's that much more inconvenient to write:
 
 instance NFData Int where rnf = rnf'
 instance NFData Word where rnf = rnf'
 instance NFData Integer where rnf = rnf'
 ...
 where
 rnf' :: a - ()
 rnf' a = a `seq` ()
 
 So I would vote for option 2, removing the default rnf implementation.
 If I find some time I will turn this into an official proposal.

I agree it would have been nice to have that functionality directly in
the deepseq package, or at least in a way that extends the existing
functionality rather than completely replace it. However, as you noted,
it isn't possible to do that in a backwards compatible way, unless we
hack the implementation of the DefaultSignatures extension. That being
said, even if it was possible to do this in a backwards compatible way,
I'm not entirely sure it would be desirable to do so  because there is
one subtle difference between this code and the deepseq package.

With the generic-deepseq package, you should only need to provide an
explicit DeepSeq instance for some type if it is abstract, because you
can't get a Generic instance in that case (unless the library author
derived Generic himself, but that would be a weird and dangerous thing
to do for an abstract datatype). If you're not dealing with an abstract
datatype, you _shouldn't_ have an explicit instance, because it would be
possible to write an incorrect one, while that is impossible if you just
derive a generic implementation (as long as the generic code is correct,
of course).

So, knowing that it would necessarily be backwards incompatible (I
wasn't intending to hack on GHC :-), and also that, in the end, this is
not quite the same class as the NFData class from the deepseq package, I
thought it made more sense to create another package that would be
mostly compatible with deepseq, but with a different class name so as to
force people to reevaluate the need for their instances if they have
some. I'd be interested in knowing what you and others think about that.
Maybe I'm being overly cautious?

I kept the rest of the API identical so that it's still easy to switch
to this package, thus you can still use the ($!!), force, and rnf
functions. I'm guilty of not having preserved the rnf :: a - ()
function as the class function though, it's a wrapper around deepseq
in my code. I just didn't see the point of having a class function with
such a signature versus having a function just like seq :: a - b -
b. In retrospect, that might have been a bad idea, and maybe I should
switch to have an rnf :: a - () class function to make switching even
easier?

Thanks a lot for your input!

Maxime Henrion


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: generic-deepseq 1.0.0.0

2012-02-19 Thread Maxime Henrion
On Sun, 2012-02-19 at 21:06 +0100, Bas van Dijk wrote:
 On 19 February 2012 18:11, Maxime Henrion mhenr...@gmail.com wrote:
  If you're not dealing with an abstract datatype, you _shouldn't_ have an
  explicit instance, because it would be possible to write an incorrect one,
  while that is impossible if you just derive a generic implementation
  (as long as the generic code is correct, of course).
 
 I agree. I hadn't considered this advantage yet. I guess it's the same
 argument for why it's better to automatically derive Data and Typeable
 instances using the DeriveDataTypeable extension.
 
  So, knowing that it would necessarily be backwards incompatible (I
  wasn't intending to hack on GHC :-), and also that, in the end, this is
  not quite the same class as the NFData class from the deepseq package, I
  thought it made more sense to create another package that would be
  mostly compatible with deepseq, but with a different class name so as to
  force people to reevaluate the need for their instances if they have
  some. I'd be interested in knowing what you and others think about that.
  Maybe I'm being overly cautious?
 
 I do think it's better to integrate this into the deepseq package (and
 thus removing the default implementation of rnf). Otherwise we end up
 with two ways of evaluating values to normal form.

I'm okay with that, but I was interested in knowing whether you think my
reasoning for changing the class name and thus deliberately breaking the
API slightly more was sane or not (I say more because removing the
default implementation of rnf already constitutes an API breakage in
that the generic replacement would be optional and depends on having
Generic instances to work).

  I'm guilty of not having preserved the rnf :: a - ()
  function as the class function though, it's a wrapper around deepseq
  in my code. I just didn't see the point of having a class function with
  such a signature versus having a function just like seq :: a - b -
  b. In retrospect, that might have been a bad idea, and maybe I should
  switch to have an rnf :: a - () class function to make switching even
  easier?
 
 I'm not sure but maybe a method like rnf :: a - () is easier to optimize.
 
 Also in my experience (with generics support in aeson and cereal) it's
 a very good idea (performance-wise) to INLINE your methods like I did
 in my previous message. Of course the only way to know for sure is the
 create some (criterion) benchmarks.

Yeah, I should definitely get going on the benchmarks.

 One last issue: Say I have a type like: data T = C !Int
 Currently GHC Generics can't express the strictness annotation. This
 means that your deepseq will unnecessarily evaluate the Int (since it
 will always be evaluated already). It would be nice if the strictness
 information could be added to the K1 type. (José, would it be hard to
 add this to GHC.Generics?)

Assuming there is way to differentiate strict constructors in
GHC.Generics, and that I have a specific instance so as to not call seq
in that case, can you actually do such an optimization safely? Consider
this code (imports omitted for simplicity):

data T = C !Int deriving Generic

instance DeepSeq T

x :: T
x = undefined

main :: IO ()
main = print (x `deepseq` ())

I would expect this to diverge, just like it does if one uses `seq`. If
we implement the optimization you suggest, I believe that deepseq
wouldn't diverge, but I admit I'm not 100% sure either.

Cheers,
Maxime Henrion


signature.asc
Description: This is a digitally signed message part
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] DFAs and self-referential data

2010-12-26 Thread Maxime Henrion
Hello all,


I've been playing with some code to work with DFAs, but I'm now faced
with an implementation problem.  In order to have states that can
transition to themselves, it seems I would need self-referential data;
otherwise I would need to separate those transitions from the rest and
handle them specially in the code.  I tried to exploit laziness in order
to get self-referential data as shown in the 'self' function below:

module DFA where

import Data.Map (Map)
import qualified Data.Map as M

data DFA a =
  DFA
(Map a (DFA a)) -- The set of transitions functions
Bool-- Is this a final state?

accept :: Ord a = DFA a - [a] - Bool
accept (DFA _ f)  [] = f
accept (DFA ts f) (x:xs) = maybe False (`accept` xs) (M.lookup x
ts)

empty :: Bool - DFA a
empty = DFA M.empty

path :: Ord a = a - DFA a - DFA a - DFA a
path x d' (DFA ts f) = DFA (M.insert x d' ts) f

self :: Ord a = a - DFA a - DFA a
self x d = let d' = path x d' d in d'

test :: String - Bool
test = accept s1
  where s1 = path '0' s2 . self '1' $ empty True
s2 = path '0' s1 . self '1' $ empty False


The automaton I construct in the 'test' function is the example one from
the wikipedia page
(http://en.wikipedia.org/wiki/Deterministic_finite_automaton) on DFAs.
It should accept any string formed with ones and zeros that contain an
even number of zeros (or, equivalently, strings that match the regular
expression 1*(0(1*)0(1*))*).

Unfortunately, this doesn't seem to give the desired effect:

*DFA test 0
False
*DFA test 00
True
*DFA test 000
False
*DFA test 
True
*DFA test 1
True
*DFA test 11
True
*DFA test 111
True
*DFA test 11100
False

Anyone knows what I'm doing wrong here?  I suspect my attempt at having
self-referential data is somehow buggy; do I need to treat transitions
to the same state differently?

Cheers,
Maxime


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] DFAs and self-referential data

2010-12-26 Thread Maxime Henrion
On Sun, 2010-12-26 at 13:58 +0200, Roman Cheplyaka wrote:
 * Maxime Henrion mhenr...@gmail.com [2010-12-26 12:01:31+0100]
  Anyone knows what I'm doing wrong here?  I suspect my attempt at having
  self-referential data is somehow buggy; do I need to treat transitions
  to the same state differently?
 
 The problem is that when you call 'self', you record *that* state of
 your DFA in the map. When DFA gets updated further, the recorded
 self-reference is not updated appropriately.
 
 In your case a workaround is to call 'self' after all the other updates,
 i.e.
 
 test :: String - Bool
 test = accept s1
   where s1 = self '1' . path '0' s2 $ empty True
 s2 = self '1' . path '0' s1 $ empty False
 
 But I don't see why you need 'self' at all -- you can just use path as
 with any other type of transition:
 
 test :: String - Bool
 test = accept s1
   where s1 = path '0' s2 . path '1' s1 $ empty True
 s2 = path '0' s1 . path '1' s2 $ empty False

Indeed this just works, thanks!  The reason I was using a 'self'
function was that I initially thought it would be more convenient; I now
see it doesn't, especially considering it doesn't even work.  However
I'm a bit confused as to why things just work without having to reorder
the calls when using the 'path' function - my brain seems to have
difficulties following the code path here :-).

Cheers,
Maxime


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] DFAs and self-referential data

2010-12-26 Thread Maxime Henrion
On Sun, 2010-12-26 at 13:38 +0100, Maxime Henrion wrote:
 On Sun, 2010-12-26 at 13:58 +0200, Roman Cheplyaka wrote:
  * Maxime Henrion mhenr...@gmail.com [2010-12-26 12:01:31+0100]
   Anyone knows what I'm doing wrong here?  I suspect my attempt at having
   self-referential data is somehow buggy; do I need to treat transitions
   to the same state differently?
  
  The problem is that when you call 'self', you record *that* state of
  your DFA in the map. When DFA gets updated further, the recorded
  self-reference is not updated appropriately.
  
  In your case a workaround is to call 'self' after all the other updates,
  i.e.
  
  test :: String - Bool
  test = accept s1
where s1 = self '1' . path '0' s2 $ empty True
  s2 = self '1' . path '0' s1 $ empty False
  
  But I don't see why you need 'self' at all -- you can just use path as
  with any other type of transition:
  
  test :: String - Bool
  test = accept s1
where s1 = path '0' s2 . path '1' s1 $ empty True
  s2 = path '0' s1 . path '1' s2 $ empty False
 
 Indeed this just works, thanks!  The reason I was using a 'self'
 function was that I initially thought it would be more convenient; I now
 see it doesn't, especially considering it doesn't even work.  However
 I'm a bit confused as to why things just work without having to reorder
 the calls when using the 'path' function - my brain seems to have
 difficulties following the code path here :-).

Oh, nevermind, I finally figured it out.  When using my 'self' function,
as you said, I point at the version of the DFA I have when calling
'self', and not the final version of the DFA after other calls to
'path'.  So as soon as I was following a self transition, I was ending
up with an 'old' version of the DFA.  Whereas in your version, the
binding I point to is the final DFA version.

Thanks a lot!

Maxime


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Defining a CPP macro when building documentation

2009-05-24 Thread Maxime Henrion
Hello all,


I have been exposed to a problem that have happened to others too, and
since I have found a (scary) solution with the help of Duncan Coutts,
I'm now sharing it with you.

The reason I wanted to pass specific CPP flags to haddock was to allow
the documentation of the full module to get built, even when only parts
of the module would end up getting compiled because of restrictions on
the build platform.

In this mail, Duncan Coutts gives a very helpful bit of code to override
the haddockHook and pass additional options to haddock :

http://www.haskell.org/pipermail/haskell-cafe/2008-December/051785.html

In my case, I needed something very similar, except that I needed to
pass those additional options to hsc2hs which my code uses.  This worked
fine as long as the cabal commands sequence was [configure,haddock]
and not [configure,build,haddock].  The reason for this is that in
the latter case, the library wasn't being processed again, but output of
previous runs of hsc2hs were reused.

So I worked around this with an ugly hack that removes the .hs files
before running haddock, in order to force re-processing!  Here's the
final code I ended up with :

import Distribution.Simple
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(withPrograms), 
buildDir)
import Distribution.Simple.Program (userSpecifyArgs)

import System.Directory
import System.FilePath

-- Define __HADDOCK__ when building documentation.
main = defaultMainWithHooks simpleUserHooks {
  haddockHook = \pkg lbi h f - do
let progs = userSpecifyArgs hsc2hs [-D__HADDOCK__] (withPrograms lbi)
removePreProcessedFiles (buildDir lbi)
haddockHook simpleUserHooks pkg lbi { withPrograms = progs } h f
}

-- Horrible hack to force re-processing of the .hsc file.  Otherwise
-- the __HADDOCK__ macro doesn't end up being defined.
removePreProcessedFiles :: FilePath - IO ()
removePreProcessedFiles dir =
  removeFile (dir / System/BSD/Sysctl.hs)
`catch` \_ - return ()

Cheers,
Maxime

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] ANN: bsd-sysctl 1.0.3

2009-05-24 Thread Maxime Henrion
I'm pleased to announce the release of bsd-sysctl 1.0.3, a package that
provides a System.BSD.Sysctl module allowing access to the C sysctl(3)
API.

It should fully work on FreeBSD, NetBSD and Mac OS X platforms; it
should also work on OpenBSD and Linux, although looking up sysctl's by
name isn't supported there, and I believe the sysctl API doesn't return
anything useful under Linux.

The package is available here:

http://hackage.haskell.org/cgi-bin/hackage-scripts/package/bsd-sysctl-1.0.3

As this is my first package on hackage, I'm eager to hear about any
comments on this code.

Cheers,
Maxime

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Fast mutable arrays of ByteString?

2009-04-15 Thread Maxime Henrion
Hello all,


I have been rewriting a small utility program of mine from C to Haskell
for fun.  This tool reads lines from stdin or from files, shuffles them
one or more times using the Fisher-Yates algorithm, and outputs the
result to stdout.

Since this algorithm is based on in-place updates, I've been storing my
strings in a mutable array in the ST monad.  Since it's holding strings
I could not use an unboxed array.  The resulting program works fine and
seems to run at a decent speed, even though it is much slower than the
original C version, slightly more so than I expected.

While trying to optimize it using profiling, and playing with the number
of shuffling passes, I noticed that this operation was responsible for a
significant amount of the runtime, much more so than with the C version.
I also noticed that the %GC time was around 56%.

In order to do more tests, I wrote another version of this program which
keeps the strings in a pure and immutable array, and stores the indices
of this array in an unboxed mutable ST array.  The shuffling is then
done on this indices array instead of the strings array.

This version runs much faster and only spends ~21% of its time in the
garbage collector, at the cost of consuming more memory for the indices
array.

I'm attaching both versions of the code to this e-mail, and I'd be
curious to hear about any possible improvements to it, and whether the
performance of STArray of ByteString I'm observing corresponds to
people's expectations.

Thanks in advance,
Maxime Henrion
{-# LANGUAGE BangPatterns #-}
module Main where

import Control.Monad
import Control.Monad.ST
 
import Data.Array.ST
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as S
import Data.Maybe

import System.Console.GetOpt
import System.Environment
import System.IO
import System.Random

data Config = Config
  { separator :: Char
  , numPasses :: Int
  } deriving (Eq, Show)

defaultConfig = Config
  { separator = '\n'
  , numPasses = 1
  }

options :: [OptDescr (Config - Config)]
options =
  [ Option ['0'] [] (NoArg (\cfg - cfg { separator = '\0' }))
  expect ASCII NUL characters as separators
  , Option ['d'] [] (OptArg ((\d cfg - cfg { separator = d }) . maybe '\n' head) delim)
  use provided character as separator
  , Option ['n'] [] (OptArg ((\n cfg - cfg { numPasses = n }) . readNumPasses) npass)
  run # passes instead of just 1
  ]
 where readNumPasses = maybe 1 (headMaybe 1 fst . reads)
   headMaybe _ f [x] = f x
   headMaybe d _ _   = d

main :: IO ()
main = do argv - getArgs
  case getOpt RequireOrder options argv of
(opts, args, []) - do g - newStdGen
   input - getInput args
   let Config { separator = sep
  , numPasses = n
  } = foldl (flip id) defaultConfig opts
   forM_ (shuffle g n (slice sep input)) $ \ln -
 S.putStr ln  putChar sep
(_,  _, (err:_)) - do prog - getProgName
   hPutStr stderr (prog ++ :  ++ err)

getInput :: [FilePath] - IO ByteString
getInput [] = S.getContents
getInput ps = S.concat `fmap` mapM S.readFile ps

slice :: Char - ByteString - (Int, [ByteString])
slice d s = slice' d s 1 []
  where
slice' d s !count lns =
  case S.elemIndex d s of
Nothing- (count, s:lns)
Just n
 | n == S.length s - 1 - (count, S.take n s:lns) -- ignore empty trailing lines
 | otherwise   - slice' d (S.drop (n + 1) s) (count + 1) (S.take n s:lns)
{-# INLINE slice #-}

shuffle :: RandomGen g = g - Int - (Int, [ByteString]) - [ByteString]
shuffle g n (count,lns) =
  runST $ do
arr - newListArray (0,count - 1) lns :: ST s (STArray s Int ByteString)
forM_ swaps $ \(i,j) -
  when (i /= j) $ do
tmp - readArray arr i
readArray arr j = writeArray arr i
writeArray arr j tmp 
getElems arr
  where swaps = zipWith (\n k - (n - 1, k `mod` n))
  (concat $ replicate n [count,count-1..2]) (randoms g)
{-# LANGUAGE BangPatterns #-}
module Main where

import Control.Monad
import Control.Monad.ST
 
import Data.Array
import Data.Array.ST
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as S
import Data.Maybe

import System.Console.GetOpt
import System.Environment
import System.IO
import System.Random

data Config = Config
  { separator :: Char
  , numPasses :: Int
  } deriving (Eq, Show)

defaultConfig = Config
  { separator = '\n'
  , numPasses = 1
  }

options :: [OptDescr (Config - Config)]
options =
  [ Option ['0'] [] (NoArg (\cfg - cfg { separator = '\0' }))
  expect ASCII NUL characters as separators
  , Option ['d'] [] (OptArg ((\d cfg - cfg { separator = d }) . maybe '\n' head

[Haskell-cafe] Space leak with Data.Binary and decodeFile

2009-01-11 Thread Maxime Henrion
Hello all,


I've been observing a huge space leak with some code using Data.Binary
that I cannot make sense of and I hope someone here can shed some light
on this, so I'll try to explain my problem as clearly as possible.  I
qualify the space leak as huge because if I let the program run, it will
soon consume the whole memory available (~3G) and finally will get
killed by the system.

The code I'm writing implements a search algorithm using an inverted
index.  This index is built from a Trie [Int] (from the bytestring-trie
package) and an Array Int ByteString.  The trie maps each referenced
word to an integer list that is a list of indices into the array.  Here
is the code for the Index datatype and the obvious Binary instance:

data Index = Index { entries :: Array Int ByteString
   , invidx  :: Trie [Int
   }

instance Binary Index where
put (Index dirs idx) = put dirs  put idx
get = liftM2 get get

I have no problems creating and seralizing this data structure to a
file.  The huge leak appears instead when I'm reading this data
structure from a file and try to do something with it.

This is the smallest test case I came up with that can reproduce the
problem :

main = do idx - decodeFile list.idx; mapM_ (B.putStrLn . snd) (assocs
(entries idx))

The space leak also appears when I try to touch the trie instead of the
array.  I've been trying tons of combinations involving adding or
removing strictness annotations and seq calls in various places with no
luck.  I have also been adding SCC annotations and tried to profile the
code.  This seemed to suggest the space leak happens in the get method
of the Array instance of Binary :

instance (Binary i, Ix i, Binary e) = Binary (Array i e) where
[...]
get = do
bs - get
n  - get  -- read the length
xs - replicateM n get -- now the elems.
return (listArray bs xs)

The output of the profiler tells me that all the space gets allocated
from the replicateM n get expression.

Now for the really weird part: if I load my code in GHCi and type
main, I can observe the space leak.  However, if I copy paste the
definition of main instead, the code runs fine!  This is the only
circumstance I've seen this code work instead of eating all the RAM...

I have been using GHC 6.10.1, binary 0.4.4 and bytestring-trie 0.1.2.

If there's anything else that I can do to understand what's going on, I
would gladfully hear about it.  Please also tell me if I should provide
more information.

Thanks,
-- 
Maxime Henrion

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Why functional programming matters

2008-01-23 Thread Maxime Henrion
Simon Peyton-Jones wrote:
 Friends
 
 Over the next few months I'm giving two or three talks to groups of *non* 
 functional programmers about why functional programming is interesting and 
 important.  If you like, it's the same general goal as John Hughes's famous 
 paper Why functional programming matters.
 
 Audience: some are technical managers, some are professional programmers; but 
 my base assumption is that none already know anything much about functional 
 programming.
 
 Now, I can easily rant on about the glories of functional programming, but 
 I'm a biased witness -- I've been doing this stuff too long.  So this message 
 is ask your help, especially if you are someone who has a somewhat-recent 
 recollection of realising wow, this fp stuff is so cool/useful/powerful/etc.
[...]

I think I qualify for this: I've been a long time C coder (and still
do some), doing mostly UNIX/system stuff, most notably working on
the FreeBSD kernel.  I only recently (1 year, maybe one and a half)
started learning Haskell so I still have fresh memories about my
first feelings.  One of the things that particularly impressed me
was parametric polymorphism.

As a C programmer, you tend to rewrite code to deal with linked
lists every time you need one, adding next pointers to some structure
of yours.  This kind of things get boring fast (one could also use
the BSD sys/queue.h macros, but they're ugly).

So when I discovered about parametric polymorphism, and how you can
have, for instance, a length :: [a] - Int function working for
any kind of lists, I was _very_ impressed.  In a way, it is all
perfectly logical to be able to have this kind of functions, since
length doesn't need to know anything about what the list is holding,
but it doesn't make it any less impressive for a C coder.

Still on the parametric polymorphism topic, the Maybe datatype is
what impressed me next.  Everyone that has done some amount of C
in his life knows how boring it is to have functions returning
errors to the caller.  If you're lucky, your function returns a
pointer and can thus return NULL in case something went wrong.  If
your function returns an int and -1 has no meaning, you can use
that too.  But if you don't, it becomes messy quickly.  It's even
more annoying when the standard got it wrong, for instance the
dreaded atoi() function.  So, when I discovered the Maybe datatype,
I was like a kid opening presents at christmas :-).  The extreme
simplicity of the definition of the Maybe datatype is impressive
in itself, its convenience is as well, and the fact that it prevents
a whole class of bugs by making it (nearly) impossible to ignore
the fact that the function can fail is the cherry on top.

Here are my $0.02 :-).  I hope they'll be useful to you.  This is
mostly emotional and subjective stuff rather than technical, but I
believe this is also what you're looking after.

Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] freebsd-7.0BETA1 and ghc

2007-10-25 Thread Maxime Henrion
brad clawsie wrote:
 On Wed, Oct 24, 2007 at 06:14:49PM -0400, Xiao-Yong Jin wrote:
  Is there any hope for it to be fixed before the freeze of
  ports tree? 
 
 i believe that is the purpose of the extended beta/rc period, to allow
 ports maintainers a chance to get things fixed before the main release
 
 as it stands a fix was submitted by a user but has not been entered
 into the main ports tree (yet):
 
 http://www.freebsd.org/cgi/query-pr.cgi?pr=117235 
 
 my impression of freebsd beta releases is that the term beta is not
 being casually applied (like google etc), but is a true cautionary label

I'll try to coordinate with fellow FreeBSD developers who are interested
in Haskell, in order to ensure we'll get GHC for FreeBSD 7 soon enough.
I am not sure however, that it will happen in time for 7.0-RELEASE.  The
ports freeze is currently planned for October 30.

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] wordsBy in the base libraries?

2007-10-22 Thread Maxime Henrion
Hello all,


What do you think about having a wordsBy function in the standard
libraries?  It often comes in handy.

 wordsBy :: (a - Bool) - [a] - [[a]]
 wordsBy p s = case dropWhile p s of
   []  - []
   ':rest - (s':w) : wordsBy p s''
 where (w, s'') = break p rest

This version takes care of avoiding a redundant character check that
is present in the standard definition of the words function, originally
discovered by Neil Mitchell, see his blog post here:

http://neilmitchell.blogspot.com/2007/07/equational-reasoning-in-haskell.html

Then we can define the  words function naturally:

 words :: String - [String]
 words = wordsBy isSpace

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] wordsBy in the base libraries?

2007-10-22 Thread Maxime Henrion
This got a bit mangled, here's the fixed version:

  wordsBy :: (a - Bool) - [a] - [[a]]
  wordsBy p s = case dropWhile p s of
[]  - []
s':rest - (s':w) : wordsBy p s''
  where (w, s'') = break p rest
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] wordsBy in the base libraries?

2007-10-22 Thread Maxime Henrion
Jules Bean wrote:
 Maxime Henrion wrote:
  Hello all,
 
 
 What do you think about having a wordsBy function in the standard
 libraries?  It often comes in handy.
 
 I speculate (but don't know) that the reason we don't have one is that 
 there are quite a few choices to make:
 
 * delimiter as function (Char - Bool) or Char
 * delimit by single chars only or multiple (String - Bool)
 * multiple adjacent delimiters cause empty items, or not?
 * exact delimiter which occured returned as part of the result?
 
 ... my anecdotal experience is that in practice for slightly different 
 applications you need different permutations of these choices. A single 
 function which encompassed all the options would have a cumbersome type.

I fully agree with you in that we often need slight variations of such a
function, and that writing one that encompasses all different uses would
probably be less convenient to use.  However, we could argue just the
same about the words function.  Since it's there, and that it's going
to stay, I still find the wordsBy function nice to have in the
standard libraries.  Besides, it seems to me we often need that
particular behaviour of words (single character matches, eating empty
items).  

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] more functions to evaluate

2007-10-12 Thread Maxime Henrion
Isaac Dupree wrote:
 Dan Weston wrote:
 applyNtimes :: (a - a) - Int - a - a
 
 This sounds like it should be in the library somewhere
 
 agree, I've used it a few times (mostly for testing things) - modulo 
 argument order and Int vs. Integer vs. (Num a = a)

What do you think about calling it iterateN instead?

Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] more functions to evaluate

2007-10-12 Thread Maxime Henrion
Dan Weston wrote:
 I like that name, and will henceforth use it myself until someone sees 
 fit to add it to the Prelude!

Oh, and I guess we'd also need:

genericIterateN :: (a - a) - Integer - a - a

Which also got me thinking, wouldn't it make more sense to have the
count as the first parameter?

iterateN:: Int - (a - a) - a - a
genericIterateN :: Integer - (a - a) - a - a

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] more functions to evaluate

2007-10-12 Thread Maxime Henrion
Maxime Henrion wrote:
 Dan Weston wrote:
  I like that name, and will henceforth use it myself until someone sees 
  fit to add it to the Prelude!
 
 Oh, and I guess we'd also need:
 
 genericIterateN :: (a - a) - Integer - a - a
 
 Which also got me thinking, wouldn't it make more sense to have the
 count as the first parameter?
 
 iterateN:: Int - (a - a) - a - a
 genericIterateN :: Integer - (a - a) - a - a

Woops, obviously I meant:

genericIterateN :: Integral a = a - (b - b) - b - b

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: Haskell FFI and finalizers

2007-10-09 Thread Maxime Henrion
Simon Marlow wrote:
 Maxime Henrion wrote:
 Stefan O'Rear wrote:
 On Thu, Oct 04, 2007 at 12:55:41AM +0200, Maxime Henrion wrote:
 When writing the binding for foo_new(), I need to open a file with
 fopen() to pass it the FILE *.  Then I get a struct foo * that I can
 easily associate the the foo_destroy() finalizer.  However, when
 finalizing the struct foo * object, I want to also close the FILE *
 handle.
 
 If I write a small C function for doing the finalizer myself, I still
 wouldn't get passed the FILE * to close, only the struct foo * pointer
 which is of no use.
 Ah, yes, this does make the situation more interesting.
 
 Looks like newForeignPtrEnv is maybe what you want?
 
 Yeah, this is what I use now.  I wrote a player_finalizer() function in
 C, that takes a FILE * and a pointer to the struct I'm handling, and
 which just closes the file.  I then added these sources to the mix in my
 .cabal file (with C-Sources, Extra-Includes, etc), and registered this
 new finalizer using addForeignPtrFinalizerEnv.
 
 This makes me want to ask you, what is so bad about Foreign.Concurrent
 that it should be avoided at almost any cost?  It sure is likely to be
 much slower than just calling a plain C finalizer, but aren't Haskell
 threads super-cheap anyways?
 
 In GHC ordinary ForeignPtr finalizers are implemented using 
 Foreign.Concurrent anyway.  It's not so much that Foreign.Concurrent should 
 be avoided at all costs, but rather finalizers in general should be 
 avoided, especially if you really care about when they run (i.e. bad things 
 could happen if they run late or at unpredictable times).
 
 The Haskell code is not run by the garbage collector, rather the garbage 
 collector figures out which finalizers need running and creates a thread to 
 run them.  It's perfectly safe to have C finalizers that invoke Haskell 
 code using GHC, although this is explicitly undefined by the FFI spec.
 
 The reason that Foreign.Concurrent is separate from Foreign.ForeignPtr is 
 that it does essentially require concurrency to implement, whereas ordinary 
 C finalizers can be run by the GC (although GHC doesn't do it this way).

Thank you for those precisions, Simon.  It seems that even if using the
Foreign.Concurrent module isn't a problem per-self, I'd be better off
using a plain C finalizer that I write myself, if only for portability
with other FFI implementations.

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Haskell FFI and finalizers

2007-10-04 Thread Maxime Henrion
Stefan O'Rear wrote:
 On Thu, Oct 04, 2007 at 12:55:41AM +0200, Maxime Henrion wrote:
  When writing the binding for foo_new(), I need to open a file with
  fopen() to pass it the FILE *.  Then I get a struct foo * that I can
  easily associate the the foo_destroy() finalizer.  However, when
  finalizing the struct foo * object, I want to also close the FILE *
  handle.
  
  If I write a small C function for doing the finalizer myself, I still
  wouldn't get passed the FILE * to close, only the struct foo * pointer
  which is of no use.
 
 Ah, yes, this does make the situation more interesting.
 
 Looks like newForeignPtrEnv is maybe what you want?

Yeah, this is what I use now.  I wrote a player_finalizer() function in
C, that takes a FILE * and a pointer to the struct I'm handling, and
which just closes the file.  I then added these sources to the mix in my
.cabal file (with C-Sources, Extra-Includes, etc), and registered this
new finalizer using addForeignPtrFinalizerEnv.

This makes me want to ask you, what is so bad about Foreign.Concurrent
that it should be avoided at almost any cost?  It sure is likely to be
much slower than just calling a plain C finalizer, but aren't Haskell
threads super-cheap anyways?

I'm not doubting your advices at all, but want to make sure I understand
all this fully :-).

Thanks again,
Maxime


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Haskell FFI and finalizers

2007-10-03 Thread Maxime Henrion
Hello all,



I have recently developed a small set of bindings for a C library, and
encountered a problem that I think could be interesting to others.

My problem was that the C function I was writing bindings to expects to
be passed a FILE *.  So, I had basically two possibles routes to take:

1) Mimic the C API and have the haskell function take a Handle.

Unfortunately, I can see no way to go from a Handle to a Ptr CFile, at
least no portable way, so I discarded this option.

2) Deviate from the C API slightly and have the haskell function take a
FilePath instead of a Handle.

This is the option I chose, and this is where things get interesting.

In order to pass a Ptr CFile (FILE *) to the C function, I had to call
fopen() myself, using a usual FFI binding:

foreign import ccall unsafe fopen
  fopen :: CString - CString - IO (Ptr CFile)

That's the easy part.  Now my problem was that I had to find a way to
automatically close this FILE * when it isn't used anymore, in order not
to leak FILE structures (and thus fds, etc).  A finalizer is typically
what I need, but unfortunately, a finalizer has a very strict shape:

type FinalizerPtr a = FunPtr (Ptr a - IO ())

That is, a finalizer can only be a pointer to a foreign function, and
the foreign function itself needs a quite specific shape.

And then I discovered Foreign.Concurrent, which allows one to associate
a plain Haskell IO action to a pointer.  The 'Foreign.Concurrent' name
is a bit misleading to me; it seems this module is named so because it
needs concurrency itself, rather than providing stuff for concurrency.

So, in the end, I've got this code:

import Foreign
import Foreign.C
import qualified Foreign.Concurrent as FC

...

data PlayerStruct
type Player = ForeignPtr PlayerStruct

...

foreign import ccall unsafe dd_newPlayer_file
  dd_newPlayer_file :: Ptr CFile - Ptr ImageStruct - IO (Ptr PlayerStruct)
foreign import ccall unsafe dd_destroyPlayer
  destroyPlayerFinal :: FunPtr (Ptr PlayerStruct - IO ())

foreign import ccall unsafe fopen
  fopen :: CString - CString - IO (Ptr CFile)
foreign import ccall unsafe fclose
  fclose :: Ptr CFile - IO CInt

...

mkFinalizedPlayer :: Ptr PlayerStruct - IO Player
mkFinalizedPlayer = newForeignPtr destroyPlayerFinal

newPlayerFile :: FilePath - Image - IO Player
newPlayerFile path image = do
  withCString path $ \cpath - do
withCString rb $ \cmode - do
  file - throwErrnoIfNull fopen:  (fopen cpath cmode)
  withForeignPtr image $ \ptr - do
player - dd_newPlayer_file file ptr = mkFinalizedPlayer
FC.addForeignPtrFinalizer player (fclose file  return ())
return player

So I'm adding the usual finalizer, and with the help of
Foreign.Concurrent, I can add a second free-form one (fclose file 
return ()), in order to close the file I opened at an appropriate time.

I'm looking forward hearing about other people's opinions, and wether
this is a correct solution to the initial problem or not.

I think there is another way to solve this, which is to provide the
finalizer still in haskell code, but export the haskell code using FFI,
so that I can use it as a plain, normal finalizer.  I'm still unsure
about this.

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Haskell FFI and finalizers

2007-10-03 Thread Maxime Henrion
Stefan O'Rear wrote:
 On Wed, Oct 03, 2007 at 05:57:58PM +0200, Maxime Henrion wrote:
  I have recently developed a small set of bindings for a C library, and
  encountered a problem that I think could be interesting to others.
  
  My problem was that the C function I was writing bindings to expects to
  be passed a FILE *.  So, I had basically two possibles routes to take:
 
  That's the easy part.  Now my problem was that I had to find a way to
  automatically close this FILE * when it isn't used anymore, in order not
  to leak FILE structures (and thus fds, etc).  A finalizer is typically
  what I need, but unfortunately, a finalizer has a very strict shape:
  
  type FinalizerPtr a = FunPtr (Ptr a - IO ())
  
  That is, a finalizer can only be a pointer to a foreign function, and
  the foreign function itself needs a quite specific shape.
  
  And then I discovered Foreign.Concurrent, which allows one to associate
  a plain Haskell IO action to a pointer.  The 'Foreign.Concurrent' name
  is a bit misleading to me; it seems this module is named so because it
  needs concurrency itself, rather than providing stuff for concurrency.
 
 NOOO!  Foreign.Concurrent, as its name implies, works by forking
 threads, and it should be avoided at almost any cost.  The correct
 solution is:
 
 void close_file_finalizer(FILE *file) {
 if (fclose(file)  0) {
 /* do something sensible here */
 }
 }

That wouldn't work; my problem is that this finalizer for closing the
FILE * needs to be called when another pointer gets garbage collected.
This is because I'm opening the file in order to pass to some function
which creates an objet and returns it to me.

To parody the situation:

struct foo *foo_new(FILE *);
void foo_destroy(struct foo *);

When writing the binding for foo_new(), I need to open a file with
fopen() to pass it the FILE *.  Then I get a struct foo * that I can
easily associate the the foo_destroy() finalizer.  However, when
finalizing the struct foo * object, I want to also close the FILE *
handle.

If I write a small C function for doing the finalizer myself, I still
wouldn't get passed the FILE * to close, only the struct foo * pointer
which is of no use.

Thanks,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] standard function

2007-06-06 Thread Maxime Henrion
Steffen Mazanek wrote:
 Hello,
 
 is there a function f::[a-b]-a-[b] in the libraries? Couldn't find one
 using
 hoogle although this seems to be quite a common thing...

As far as I know, there is no standard function doing that, though it is
easily implemented:

mapApply xs x = map ($ x) xs

or just:

mapApply x = map ($ x)

If you don't mind the parameters being reversed.

The 'mapApply' name is probably terrible, I'm sure other people would
have better suggestions for the naming :-).

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] GHC 6.7 and Associated Types

2007-04-17 Thread Maxime Henrion
Hello guys,


I've been documenting myself on associated types, which look like a very
nice way to deal with the problems that arise with multi-parameter type
classes.  As an exercise, I am trying to rewrite the MonadState type
class from the mtl package without functional dependencies.

Here is my (probably very naive) approach :

class MonadState m where
  type StateType m :: *
  get  :: m StateType
  put  :: m StateType - m ()

As for instances:

instance MonadState (State s) where
  type StateType = s -- this is line 22
  get= State $ \s - (s, s)
  put s  = State $ \_ - ((), s)

I think I'm probably doing some very stupid thing and missing important
points.  In any case, here's the error I get :

State.hs:22:19: Not in scope: type variable `s'
Failed, modules loaded: none.

I'd be happy to be explained why this doesn't make sense, and how I
should proceed to implement this correctly.  I have tried various other
approaches with no luck yet.

Thanks,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: GHC 6.7 and Associated Types

2007-04-17 Thread Maxime Henrion
apfelmus wrote:
 Maxime Henrion wrote:
  class MonadState m where
type StateType m :: *
get  :: m StateType
put  :: m StateType - m ()
  
  As for instances:
  
  instance MonadState (State s) where
type StateType = s -- this is line 22
 
 When defining the type function StateType, you have to give it the
 required argument m = State s:
 
 type StateType (State s) = s
 
get= State $ \s - (s, s)
put s  = State $ \_ - ((), s)

I tried that too already, it gives:

State.hs:19:39:
Kind mis-match
Expected kind `k - *', but `()' has kind `*'
In the type `m ()'
In the type `m StateType - m ()'
In the class declaration for `MonadState'

Line 19 being the definition of put in the class.

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: GHC 6.7 and Associated Types

2007-04-17 Thread Maxime Henrion
Simon Peyton-Jones wrote:
 Associated *data* types should work in the HEAD (=6.7).  But associated *type 
 synonyms* do not, I'm afraid. We are actively working on it, but it'll be a 
 couple of months at least I guess.
 
 You can see the state of play, and description of where we are up to here
 http://hackage.haskell.org/trac/ghc/wiki/TypeFunctions

Ah, it's good to know that it wasn't just me being stupid :-).

Thank you,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: GHC 6.7 and Associated Types

2007-04-17 Thread Maxime Henrion
apfelmus wrote:
 Maxime Henrion wrote:
  apfelmus wrote:
  Maxime Henrion wrote:
  class MonadState m where
type StateType m :: *
get  :: m StateType
put  :: m StateType - m ()
 
  As for instances:
 
  instance MonadState (State s) where
type StateType = s -- this is line 22
  When defining the type function StateType, you have to give it the
  required argument m = State s:
 
  type StateType (State s) = s
 
get= State $ \s - (s, s)
put s  = State $ \_ - ((), s)
  
  I tried that too already, it gives:
  
  State.hs:19:39:
  Kind mis-match
  Expected kind `k - *', but `()' has kind `*'
  In the type `m ()'
  In the type `m StateType - m ()'
  In the class declaration for `MonadState'
 
 Ah, oh, I didn't even check whether the types in the class are good. I'm
 not sure, but don't you want
 
   class MonadState m where
  type StateType m :: *
  get  :: m (StateType m)
  put  :: StateType m - m ()

 ? Then, the substitutions m = State s and StateType (State s) = s yields
 the expected types for put and get:
 
   get :: (State s) s
   put :: s - (State s) ()

Ah, I tried something like that too, and then I get errors in the
definition of the instance :

State.hs:23:19:
Couldn't match expected type `StateType (State s)'
   against inferred type `s' (a rigid variable)
  `s' is bound by the instance declaration at State.hs:21:27
  Expected type: State s (StateType (State s))
  Inferred type: State s s
In the expression: State $ (\ s - (s, s))
In the definition of `get': get = State $ (\ s - (s, s))

State.hs:24:19:
Couldn't match expected type `s' (a rigid variable)
   against inferred type `StateType (State s)'
  `s' is bound by the instance declaration at State.hs:21:27
  Expected type: State s ()
  Inferred type: State (StateType (State s)) ()
In the expression: State $ (\ _ - ((), s))
In the definition of `put': put s = State $ (\ _ - ((), s))

I would expect GHC to see that 'State s (StateType (State s))' is the
same as 'State s s', per the definition of StateType.  I'm not sure how
to express get differently so that it matches, and similarly for put.

If I write:

  get= State $ \s - (StateType (State s), s)

I get:

State.hs:23:34: Not in scope: data constructor `StateType'

Thanks,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] A convenient way to deal with conditional function composition?

2007-04-11 Thread Maxime Henrion
Chris Kuklewicz wrote:
 Nicolas Frisby wrote:
  Not portably.
 
  [EMAIL PROTECTED]:~$ ghc-6.4.2 -e '(  (foo++) `Data.Monoid.mappend`
  (bar++) ) END'
  foobarEND
  [EMAIL PROTECTED]:~$ ghc-6.6 -e '(  (foo++) `Data.Monoid.mappend`
  (bar++) ) END'
  fooENDbarEND
 
 
  -- 6.6 sources
  instance Monoid b = Monoid (a - b) where
  mempty _ = mempty
  mappend f g x = f x `mappend` g x
 
 
  Stefan
 
 Thanks for the reminder.  So the fixed 6.6 code is
 
  import Control.Monad(when)
  import Control.Monad.Writer(Writer,tell,execWriter)
  import Data.Monoid(Endo(..))
  
  type Writes = Writer (Endo String) ()
  
  data PieceType = Pawn | Other deriving (Eq,Show)
  type File = Int
  type Square = Int
  
  data Move = Move {
   movePiece :: PieceType,
   moveFile  :: Maybe File,
   moveTarget:: Square,
   moveIsCapture :: Bool
   --movePromotion :: Maybe PieceType
 }
deriving (Eq)
  
  instance Show Move where showsPrec = showsPrec_Move
  
  tShow :: Show a = a - Writes
  tShow = tell . Endo . shows
  
  tChar :: Char - Writes
  tChar = tell . Endo . (:)
  
  tString :: String - Writes
  tString = tell . Endo . (++)
  
  showsPrec_Move :: Int - Move - ShowS
  showsPrec_Move _ Move { movePiece = p
, moveFile  = f
, moveTarget= s
, moveIsCapture = c } = appEndo . execWriter $ do
when (p/=Pawn) (tShow p)
maybe (return ()) tShow f
when c (tChar 'x')
tShow s
  
  testMove = Move Other (Just 6) 10 True

Thanks a lot for all the nice answers, guys.

I have a few remaining questions if you don't mind though.  Should
I expect significant performance reduction by using the Writer monad
here, as opposed to the version I wrote?  And, most importantly,
I'd like to know how *you* would write this if you had to :-).
Would you juse the Writer monad version?

Thanks,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] A convenient way to deal with conditional function composition?

2007-04-10 Thread Maxime Henrion
Hello all,


I have found myself writing instances of Show for some types of
mine, and I did so by defining the showsPrec function, for performance
reasons.  I ended up with code that I find quite inelegant.  Here's
an example:

data Move = Move {
 movePiece :: PieceType,
 moveFile  :: Maybe File,
 moveTarget:: Square,
 moveIsCapture :: Bool
 --movePromotion :: Maybe PieceType
   }
  deriving (Eq)

instance Show Move where
  showsPrec _
Move {
  movePiece = p,
  moveFile  = f,
  moveTarget= s,
  moveIsCapture = c
} = (if p /= Pawn then shows p else id) .
(maybe id shows f) .
(if c then ('x':) else id) .
shows s

I considered writing a conditional composiion combinator to avoid all
the 'if foo then f else id' code.  Something looking like this:

f .? True  g = f . g
f .? False g = f

I'm not sure this is the best approach though, and I would be happy
to hear about your suggestions for improving the style of this code,
or any other comment that you think is appropriate.

Thanks,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Haskell Chess

2007-03-19 Thread Maxime Henrion
Steffen Mazanek wrote:
 Hello again,
 
 first of all, thank you Don for your help in making hsChess accessible. 
 I have
 to have a look at darcs and cabal first :-)
 
 I have added some more content and a discussion page to the wiki, please
 contribute your thoughts.
 
 Furthermore I added a link to the german project and task description used
 in the exercises; the English version will be the wiki (although it has 
 no convert2tex
 function).
 
 Best regards,
 Steffen

I stepped onto your mail and found it particularly interesting since
I'm currently writing a chess client in Haskell, using GTK+, glade
and the nice Cairo library :-).  It is called LambdaChess!

The code is completely embryonic and totally useless at the moment,
but there's a base for a decent GUI interface, with an SVG board,
so easily themable.  There is also some base code for a PGN file
parser written using Parsec, and the whole thing is cabalized.

The pieces aren't even drawn yet, but that should be quite easy to
do, and I've found a few nice SVG piece sets.  The PGN parser doesn't
completely parses SAN moves yet, nor does it parse NAG annotations.
It doesn't properly validates the presence of the mandatory tags,
and so on...  I guess I should stop since it's going to be huge if
I'm listing all the missing features :-).

Ultimately, it'd be nice if this code was able to handle local games
between two humans and also playing against the various chess engines
(crafty, gnuchess, sjeng, etc...).  If it was also able to connect
to FICS, it would be the absolute greatness :D.

If you or anyone else on this mailing list feels like joining the
fun, please do!

The code is available here:

  http://mu.org/~mux/LambdaChess/

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Haskell Chess

2007-03-19 Thread Maxime Henrion
Andrew Wagner wrote:
 Steffen,
 I've done some chess AI programming in the past, so I'd be happy to
 help with this project. I have some pretty fundamental design
 suggestions that I'll write up for the wiki page.
 
 Maxime,
 Handling different chess engines isn't hard. chess engine
 communication is pretty standardized - you would just need to add
 support for the winboard and/or UCI protocols. FICS is a little bit
 harder, but it's just a pure test stream over a socket, somewhat like
 IRC, but less defined. ICC (another chess server) has a slightly
 better-defined protocol. I can get you more details on any of these
 protocols (except maybe FICS, which I don't think is documented), if
 you'd like. By the way, how portable is your graphics code going to
 be?

I haven't yet looked in details at the winboard protocol or UCI,
but having used crafty and gnuchess in CLI, I have a pretty good
idea how this is all working, and this is indeed what I intend to
do.

As for FICS, I have often played on it through telnet, so I have a
good knowledge of this text-based protocol.  I don't know of any
standard for FICS, but it isn't strictly required to get something
working.  I'd be interested in ICC support too, but since it's not
free, it'll have to wait :-).

As for the portability of the my graphics code, I can just say it's
GTK+, using Glade XML files, Cairo and SVG on top of Cairo.  All
of this is supposed to work fine on Windows, if that's what you
were asking.  I'm not sure about OS X but I think it could also
work there.  My primary target is UNIX.  For those of you who know
it, I think BabasChess under Windows sums up what I'd like to obtain
in the end quite nicely, features-wise.

I'm looking forward receiving your patches! ;-)

Cheers,
Maxime

 Sounds like this will be an interesting project. I look forward to it!
 
 Andrew
 
 On 3/19/07, Duncan Coutts [EMAIL PROTECTED] wrote:
 On Mon, 2007-03-19 at 12:14 +0100, Maxime Henrion wrote:
 
  I stepped onto your mail and found it particularly interesting since
  I'm currently writing a chess client in Haskell, using GTK+, glade
  and the nice Cairo library :-).  It is called LambdaChess!
 
 Cool! When you have something you want to show off, we could always do
 with more expositions  screen shots etc for the Gtk2Hs website like the
 things we've got here:
 
 http://haskell.org/gtk2hs/archives/category/screenshots/
 
 
 And I'm glad someone is using the new SVG module that got added in the
 latest Gtk2Hs release :-)
 
 Duncan
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] A valuable new combinator for Parsec?

2007-03-12 Thread Maxime Henrion
Hello all,


While using the very nice option combinator of Parsec recently, it
seemed to me that it would be useful to have a more specific kind of
combinator for optional tokens that wraps the token into a Maybe type.

So, that gives:

pmaybe :: GenParser tok st a - GenParser tok st (Maybe a)
pmaybe p = option Nothing (p = return . Just)

I've been using it happily with some code of mine.  Do people think
that it would be generally useful to have in Parsec?

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] how to calculate the sum of list of lists?

2007-02-05 Thread Maxime Henrion
Miranda Kajtazi wrote:
 Help,
 
 How to calculate the sum of list of lists in Haskell?

Do you mean something of the form Num a = [[a]] - a ?

If so, this should do it:

Prelude let foo = sum . concat

Prelude foo [[1,2,3],[4,5]]
15

Cheers,
Maxime
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe