https://wiki.haskell.org/api.php?action=feedcontributions&user=Nr&feedformat=atomHaskellWiki - User contributions [en]2020-02-25T07:07:17ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Simonpj/Talk:FunWithTypeFuns&diff=33947Simonpj/Talk:FunWithTypeFuns2010-03-03T16:51:30Z<p>Nr: guarantee injectivity?</p>
<hr />
<div>= Fun with Type Functions =<br />
<br />
Here is Version 2 of our paper:<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun.pdf Fun With Type Functions (version 2)]''', Oleg Kiselyov, Ken Shan, and Simon Peyton Jones<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/FunWithTypeFuns-Apr09.pdf Slides (PDF)]'''<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/fun-with-type-funs.zip Source code]'''<br />
<br />
which will appear in the proceedings of Tony Hoare's 75th birthday celebration.<br />
<blockquote><br />
'''Abstract'''. Tony Hoare has always been a leader in writing down and proving<br />
properties of programs. To prove properties of programs automatically,<br />
the most widely used technology today is by far the ubiquitous type checker.<br />
Alas, static type systems inevitably exclude some good programs<br />
and allow some bad ones. This dilemma motivates us to describe some fun we've<br />
been having with Haskell, by making the type system more expressive<br />
without losing the benefits of automatic proof and compact expression.<br />
<p><br />
Haskell's type system extends Hindley-Milner with two distinctive<br />
features: polymorphism over type constructors and overloading<br />
using type classes. These features have been integral to Haskell<br />
since its beginning, and they are widely used and appreciated. More recently, Haskell has been enriched with<br />
''type families'', or ''associated types'', <br />
which allows functions on types to be<br />
expressed as straightforwardly as functions on values. This facility<br />
makes it easier for programmers to effectively extend the compiler by<br />
writing functional programs that execute during type-checking.<br />
</p><p><br />
This paper gives a programmer's tour of type families as they are<br />
supported in GHC today.<br />
</p></blockquote><br />
<br />
This Wiki page is a discussion page for the paper. If you are kind enough to read this paper, please help us by jotting down any thoughts it triggers off. Things to think about:<br />
* What is unclear?<br />
* What is omitted that you'd like to see?<br />
* Do you have any cool examples that are of a somewhat different character than the ones we describe? (If so, do explain the example on this page!)<br />
<br />
You can identify your entries by preceding them with four tildes. Doing so adds your name, and the date. Thus:<br />
<br />
:[[User:Simonpj|Simonpj]] 08:42, 19 April 2007 (UTC) Note from Simon<br />
<br />
If you say who you are in this way, we'll be able to acknowledge your help in a revised version of the paper.<br />
<br />
------------------------<br />
Add comments here (newest at the top):<br />
<br />
[[User:Nr|Norman Ramsey]] 16:51, 3 March 2010 (UTC) When the distinction between {{{data}}} and {{{type}}} is introduced in section 2.4, I'd like to be reassured that the compiler guarantees injectivity, and to get a brief explanation of the mechanism (I think it's the uniqueness of the value constructor, but I'm not 100% confident).<br />
<br />
[[User:Nr|Norman Ramsey]] 1 March 2010: I'd really like to see an alert before the example that introduces 'data' in a class declaration. The difference had me totally distracted from the rest of the example. <br />
<br />
[[User:Tanimoto|tanimoto]] 03:38, 20 July 2009 (UTC) Comments not aligned correctly<br />
<br />
In Appendix A, item 1, "ILLEGAL" and "OK" could be aligned with the previous comments.<br />
<br />
In Appendix A, item 3, type T5, "OK" is not aligned with the previous comments. The same goes for the signature.<br />
<br />
Some code snippets go off the right margin, I hope it's not a problem: pp. 10, 17, 18, 25, 35, 37.<br />
<br />
<br />
[[User:Bens|bens]] 01:13, 20 July 2009 (UTC) In Appendix C, "fmt1 ^ fmt2 = fmt1 ++ \x -> fmt2 x" -> "fmt1 ^ fmt2 = \x -> fmt1 ++ fmt2 x".<br />
<br />
[[User:BobAtkey|BobAtkey]] 17:39, 9 July 2009 (UTC) Could you update the reference to my "Parameterised Notions of Computation" paper to the journal version? Thanks: Robert Atkey. Parameterised Notions of Computation. Journal of Functional Programming 19: (3 & 4), pages 355-376, July 2009.<br />
<br />
[[User:Mvanier|Mvanier]] 03:14, 3 July 2009 (UTC) The source code link seems to be dead. '''SLPJ: fixed'''<br />
<br />
<br />
-------------------------<br />
'''Stuff below here refers to [http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun-v1.pdf Version 1 of the paper], now retired.'''<br />
-------------------------<br />
<br />
[[User:Oleg|Oleg]] 02:55, 3 June 2009 (UTC) <br />
<br />
Thank you indeed for all the comments and suggestions!<br />
<br />
i have dealt with all the comments and fixed all the noted problems. I<br />
have a few questions about several suggestions though. I should remark<br />
first that the complete code discussed in the paper is available,<br />
presently in our darcs repository. I guess Simon has not decided of a<br />
site to host the online version of the paper with the Appendices and<br />
the code. Incidentally, code fragments in the paper are lifted<br />
straight from the working code, using the remarkably useful<br />
\VerbatimInput.<br />
<br />
--------------------------------------<br />
<br />
[[User:Byorgey|Byorgey]] 20:07, 19 May 2009 (UTC) <br />
* p. 32:<br />
** "powerful, but the" -> "powerful, but they"<br />
* p. 33: <br />
** "commonly mentioned on Haskell mailing lists pitfall of type functions" -> "one pitfall of type functions commonly mentioned..."<br />
** "the compiler should chose" -> "should the compiler choose"<br />
<br />
[[User:bjpop|BerniePope]] 06:18, Fri 15 May 2009 (UTC) Typo in Appendix B.<br />
<br />
"GHC should noat" -> "GHC should not"<br />
<br />
[[User:Tanimoto|tanimoto]] 02:17, 15 May 2009 (UTC) Typo in references<br />
<br />
In reference [32], page 30, Oleg's last name is misspelled as "Kiselov".<br />
<br />
<br />
[[User:Ryani|Ryani]] 23:01, 14 May 2009 (UTC) Fun paper! Comments:<br />
<br />
I was writing a generic finite map a while ago and determined that the generic memoized trie was better in almost all cases; it was simpler semantically and didn't have a significant performance difference. Then you have "type Map k v = Table k (Maybe v)". Is it worth calling out this special case in its own section?<br />
<br />
Also, in respose to ChrisKuklewicz, I think the type for "cons" is correct, but perhaps one instance should be given as an example.<br />
<br />
'''To Ryan Ingram''': Just to double-check: you are saying that the<br />
implementation of generic finite maps as <br />
"type Map k v = Table k (Maybe v)" is faster that the one given in Sec<br />
3.3? That is quite interesting!<br />
<br />
<br />
<br />
[[User:Dave Menendez|Dave Menendez]] 16:52, 14 May 2009 (UTC) On page 11, you refer to a "specialised instance for Table Int that uses some custom <br />
(but innite!) tree representation for Int." Was this meant to be Integer? Surely any tree representation for Int would be large but finite. <br />
<br />
-------------------<br />
Peter Verswyvelen and I have been working on some type family fun to give us generalised partial application (even to the point of being able to cope with giving arguments, but not a function). I don't know if it really makes any interesting point that you didn't already in the paper, but it's certainly fun...<br />
<br />
<haskell><br />
{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeOperators, FlexibleInstances, FlexibleContexts #-}<br />
<br />
module Burn2 where<br />
<br />
newtype V a = V a -- A value<br />
data B a = B -- A value we don't want to provide yet<br />
<br />
-- Type level homogenous lists (well just tuples in a list-like syntax really)<br />
data Nil a = Nil<br />
data a :& b = !a :& !b<br />
<br />
infixr 5 :& <br />
<br />
class Apply funargs where<br />
type Result funargs :: *<br />
apply :: funargs -> Result funargs<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& V c :& rest) where<br />
type Result (V (a->b) :& V c :& rest) = Result (V b :& rest)<br />
apply (V f :& V a :& rest) = apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& V c :& rest) where<br />
type Result (B (a->b) :& V c :& rest) = (a->b) -> Result (V b :& rest)<br />
apply (B :& V a :& rest) = \f -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& B c :& rest) where<br />
type Result (V (a->b) :& B c :& rest) = a -> Result (V b :& rest)<br />
apply (V f :& B :& rest) = \a -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& B c :& rest) where<br />
type Result (B (a->b) :& B c :& rest) = (a->b) -> a -> Result (V b :& rest)<br />
apply (B :& B :& rest) = \f a -> apply $ V (f a) :& rest<br />
<br />
instance Apply (V a :& Nil b) where<br />
type Result (V a :& Nil b) = a<br />
apply (V a :& Nil) = a<br />
<br />
instance Apply (B a :& Nil b) where<br />
type Result (B a :& Nil b) = B a<br />
apply (B :& Nil) = B<br />
<br />
v1 = apply (V 1 :& Nil)<br />
f1 = apply (B :& Nil)<br />
v2 = apply (V negate :& V 1 :& Nil)<br />
f3 = apply (V negate :& B :& Nil)<br />
v3 = apply (V f3 :& V 1 :& Nil)<br />
</haskell><br />
<br />
[[User:Beelsebob|Beelsebob]] 13:04, 14 May 2009 (UTC)<br />
<br />
'''To Beelsebob''': I'm afraid the code does not account for the most<br />
interesting case: a function that takes a dynamic value and returns<br />
a static result. So you need to deal with functions of the type<br />
V a -> B b or B a -> V b. The literature on partial evaluation<br />
describes this issue in detail. Our tagless-final paper (Sec 4.2 of<br />
the the journal version, Delaying binding-time analysis) has a short<br />
explanation, too.<br />
<br />
--------------------------------------<br />
<br />
End of section 2.2, I think "cons :: a -> [b] -> [ResTy a b]" should be "cons :: a -> [b] -> ResTy a b"<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 15:28, 14 May 2009 (UTC)<br />
<br />
<br />
--------------------------------------<br />
<br />
End of page 19 with footnote 9. I could not simply copy and paste the URL because of a stray space after the '-' in http://okmij.org/ftp/Haskell/keyword- arguments.lhs<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 16:08, 14 May 2009 (UTC)<br />
<br />
<br />
'''To Chris Kuklewicz''', regarding the problem with footnote 9. That is an<br />
odd problem that I could not reproduce. It seems xpdf lets me cut<br />
and paste the URL in question without introducing stray spaces. BTW,<br />
the type was correct, as Ryan Ingram described. We have implemented<br />
his suggestion so to remove the confusion.<br />
<br />
--------------------------------------<br />
<br />
Typo "Mounier" --> "Monnier"<br />
<br />
[[User:Tschrijvers|Tom Schrijvers]] 11:11, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Contrary to what the introductions say, polymorphism over type constructors was not part of Haskell from the beginning. They were only introduced after Mark Jones showed how to do it in Gofer.<br />
<br />
[[User:Augustss|Augustss]] 14:30, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Why do you say "Obviously, we want to declare algebraic data kinds, ..."?<br />
What's obvious about that? Many of us think that's the wrong way, and you should instead provide a way to lift ordinary data type to the kind level.<br />
<br />
[[User:Augustss|Augustss]] 15:36, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
I was really fascinated by section 5.2 where you track state in the types using a parameterized monad. However, the example code you use is rather underwhelming since it can be implemented by much simpler means. If there's only a fixed number of locks then they can be tracked using a fixed tuple and the whole type functions business is a bit superfluous (albeit still nice). To really reap the benefits of the machinery you set up you ought to have a function for creating new locks dynamically. Here's an example of how it can be done:<br />
<haskell><br />
type family Length p<br />
type instance Length Nil = Zero<br />
type instance Length (Cons l p) = Succ (Length p)<br />
<br />
type family NewLock p<br />
type instance NewLock Nil = Cons Unlocked Nil<br />
type instance NewLock (Cons l p) = Cons l (NewLock p)<br />
<br />
newLock :: Nat (Length p) =><br />
LockM p (NewLock p) (Lock (Length p))<br />
newLock = LockM (return mkLock)<br />
</haskell><br />
<br />
In order for this to work nicely we need a new run function as well. I've used an ordinary type class to check that all locks are unlocked, since this really is a predicate on the state and not a function. <br />
<br />
<haskell><br />
class AllUnlocked a<br />
<br />
instance AllUnlocked Nil<br />
instance AllUnlocked p => AllUnlocked (Cons Unlocked p)<br />
<br />
runNew :: AllUnlocked locks => LockM Nil locks a -> IO a<br />
runNew = unLockM<br />
</haskell><br />
<br />
I think the section becomes more convincing if you add dynamic creation of locks. Not to mention the increased sex appeal :-)<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)<br />
<br />
'''To Josef Svenningsson''': indeed the variable number of locks would have<br />
been sexier but it creates the problem of locks `leaking' out of scope<br />
(e.g., returned as the result of runNew and then used within another<br />
runNew computation, with disastrous results). In short, we need<br />
regions. Chung-chieh Shan and I have indeed implemented such a system,<br />
with a parameterized monad to track the state of the variable number of<br />
resources (file handles in our case). Please see Sec 6 of our<br />
Lightweight Monadic Regions paper. We used functional dependencies for<br />
type functions. Replacing functional dependencies with type functions<br />
is straightforward. Yet the staggering complexity of the code in Sec 6<br />
will remain. I'm afraid this makes the example too complex for this<br />
paper; rather than attracting users to type functions we would scare<br />
all of them away.<br />
--------------------------------------<br />
<br />
It would be very nice if you published a bundle or repository somewhere containing the Haskell source from the paper. At the very least it would be nice with a comment on which version of GHC one should have and what flags are required. The reason I'm asking is that I had a bit of trouble with this. For instance, just saying {-# LANGUAGE TypeFamilies #-} didn't enable type equality constraints in the parser. I had to add ScopedTypeVariables which felt rather arbitrary.<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)</div>Nrhttps://wiki.haskell.org/index.php?title=Simonpj/Talk:FunWithTypeFuns&diff=33899Simonpj/Talk:FunWithTypeFuns2010-03-02T03:08:34Z<p>Nr: </p>
<hr />
<div>= Fun with Type Functions =<br />
<br />
Here is Version 2 of our paper:<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun.pdf Fun With Type Functions (version 2)]''', Oleg Kiselyov, Ken Shan, and Simon Peyton Jones<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/FunWithTypeFuns-Apr09.pdf Slides (PDF)]'''<br />
* '''[http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/fun-with-type-funs.zip Source code]'''<br />
<br />
which will appear in the proceedings of Tony Hoare's 75th birthday celebration.<br />
<blockquote><br />
'''Abstract'''. Tony Hoare has always been a leader in writing down and proving<br />
properties of programs. To prove properties of programs automatically,<br />
the most widely used technology today is by far the ubiquitous type checker.<br />
Alas, static type systems inevitably exclude some good programs<br />
and allow some bad ones. This dilemma motivates us to describe some fun we've<br />
been having with Haskell, by making the type system more expressive<br />
without losing the benefits of automatic proof and compact expression.<br />
<p><br />
Haskell's type system extends Hindley-Milner with two distinctive<br />
features: polymorphism over type constructors and overloading<br />
using type classes. These features have been integral to Haskell<br />
since its beginning, and they are widely used and appreciated. More recently, Haskell has been enriched with<br />
''type families'', or ''associated types'', <br />
which allows functions on types to be<br />
expressed as straightforwardly as functions on values. This facility<br />
makes it easier for programmers to effectively extend the compiler by<br />
writing functional programs that execute during type-checking.<br />
</p><p><br />
This paper gives a programmer's tour of type families as they are<br />
supported in GHC today.<br />
</p></blockquote><br />
<br />
This Wiki page is a discussion page for the paper. If you are kind enough to read this paper, please help us by jotting down any thoughts it triggers off. Things to think about:<br />
* What is unclear?<br />
* What is omitted that you'd like to see?<br />
* Do you have any cool examples that are of a somewhat different character than the ones we describe? (If so, do explain the example on this page!)<br />
<br />
You can identify your entries by preceding them with four tildes. Doing so adds your name, and the date. Thus:<br />
<br />
:[[User:Simonpj|Simonpj]] 08:42, 19 April 2007 (UTC) Note from Simon<br />
<br />
If you say who you are in this way, we'll be able to acknowledge your help in a revised version of the paper.<br />
<br />
------------------------<br />
Add comments here (newest at the top):<br />
<br />
[[User:Nr|Norman Ramsey]] 1 March 2010: I'd really like to see an alert before the example that introduces 'data' in a class declaration. The difference had me totally distracted from the rest of the example. <br />
<br />
[[User:Tanimoto|tanimoto]] 03:38, 20 July 2009 (UTC) Comments not aligned correctly<br />
<br />
In Appendix A, item 1, "ILLEGAL" and "OK" could be aligned with the previous comments.<br />
<br />
In Appendix A, item 3, type T5, "OK" is not aligned with the previous comments. The same goes for the signature.<br />
<br />
Some code snippets go off the right margin, I hope it's not a problem: pp. 10, 17, 18, 25, 35, 37.<br />
<br />
<br />
[[User:Bens|bens]] 01:13, 20 July 2009 (UTC) In Appendix C, "fmt1 ^ fmt2 = fmt1 ++ \x -> fmt2 x" -> "fmt1 ^ fmt2 = \x -> fmt1 ++ fmt2 x".<br />
<br />
[[User:BobAtkey|BobAtkey]] 17:39, 9 July 2009 (UTC) Could you update the reference to my "Parameterised Notions of Computation" paper to the journal version? Thanks: Robert Atkey. Parameterised Notions of Computation. Journal of Functional Programming 19: (3 & 4), pages 355-376, July 2009.<br />
<br />
[[User:Mvanier|Mvanier]] 03:14, 3 July 2009 (UTC) The source code link seems to be dead. '''SLPJ: fixed'''<br />
<br />
<br />
-------------------------<br />
'''Stuff below here refers to [http://research.microsoft.com/~simonpj/papers/assoc-types/fun-with-type-funs/typefun-v1.pdf Version 1 of the paper], now retired.'''<br />
-------------------------<br />
<br />
[[User:Oleg|Oleg]] 02:55, 3 June 2009 (UTC) <br />
<br />
Thank you indeed for all the comments and suggestions!<br />
<br />
i have dealt with all the comments and fixed all the noted problems. I<br />
have a few questions about several suggestions though. I should remark<br />
first that the complete code discussed in the paper is available,<br />
presently in our darcs repository. I guess Simon has not decided of a<br />
site to host the online version of the paper with the Appendices and<br />
the code. Incidentally, code fragments in the paper are lifted<br />
straight from the working code, using the remarkably useful<br />
\VerbatimInput.<br />
<br />
--------------------------------------<br />
<br />
[[User:Byorgey|Byorgey]] 20:07, 19 May 2009 (UTC) <br />
* p. 32:<br />
** "powerful, but the" -> "powerful, but they"<br />
* p. 33: <br />
** "commonly mentioned on Haskell mailing lists pitfall of type functions" -> "one pitfall of type functions commonly mentioned..."<br />
** "the compiler should chose" -> "should the compiler choose"<br />
<br />
[[User:bjpop|BerniePope]] 06:18, Fri 15 May 2009 (UTC) Typo in Appendix B.<br />
<br />
"GHC should noat" -> "GHC should not"<br />
<br />
[[User:Tanimoto|tanimoto]] 02:17, 15 May 2009 (UTC) Typo in references<br />
<br />
In reference [32], page 30, Oleg's last name is misspelled as "Kiselov".<br />
<br />
<br />
[[User:Ryani|Ryani]] 23:01, 14 May 2009 (UTC) Fun paper! Comments:<br />
<br />
I was writing a generic finite map a while ago and determined that the generic memoized trie was better in almost all cases; it was simpler semantically and didn't have a significant performance difference. Then you have "type Map k v = Table k (Maybe v)". Is it worth calling out this special case in its own section?<br />
<br />
Also, in respose to ChrisKuklewicz, I think the type for "cons" is correct, but perhaps one instance should be given as an example.<br />
<br />
'''To Ryan Ingram''': Just to double-check: you are saying that the<br />
implementation of generic finite maps as <br />
"type Map k v = Table k (Maybe v)" is faster that the one given in Sec<br />
3.3? That is quite interesting!<br />
<br />
<br />
<br />
[[User:Dave Menendez|Dave Menendez]] 16:52, 14 May 2009 (UTC) On page 11, you refer to a "specialised instance for Table Int that uses some custom <br />
(but innite!) tree representation for Int." Was this meant to be Integer? Surely any tree representation for Int would be large but finite. <br />
<br />
-------------------<br />
Peter Verswyvelen and I have been working on some type family fun to give us generalised partial application (even to the point of being able to cope with giving arguments, but not a function). I don't know if it really makes any interesting point that you didn't already in the paper, but it's certainly fun...<br />
<br />
<haskell><br />
{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeOperators, FlexibleInstances, FlexibleContexts #-}<br />
<br />
module Burn2 where<br />
<br />
newtype V a = V a -- A value<br />
data B a = B -- A value we don't want to provide yet<br />
<br />
-- Type level homogenous lists (well just tuples in a list-like syntax really)<br />
data Nil a = Nil<br />
data a :& b = !a :& !b<br />
<br />
infixr 5 :& <br />
<br />
class Apply funargs where<br />
type Result funargs :: *<br />
apply :: funargs -> Result funargs<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& V c :& rest) where<br />
type Result (V (a->b) :& V c :& rest) = Result (V b :& rest)<br />
apply (V f :& V a :& rest) = apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& V c :& rest) where<br />
type Result (B (a->b) :& V c :& rest) = (a->b) -> Result (V b :& rest)<br />
apply (B :& V a :& rest) = \f -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (V (a->b) :& B c :& rest) where<br />
type Result (V (a->b) :& B c :& rest) = a -> Result (V b :& rest)<br />
apply (V f :& B :& rest) = \a -> apply $ V (f a) :& rest<br />
<br />
instance (Apply (V b :& rest), a ~ c) => Apply (B (a->b) :& B c :& rest) where<br />
type Result (B (a->b) :& B c :& rest) = (a->b) -> a -> Result (V b :& rest)<br />
apply (B :& B :& rest) = \f a -> apply $ V (f a) :& rest<br />
<br />
instance Apply (V a :& Nil b) where<br />
type Result (V a :& Nil b) = a<br />
apply (V a :& Nil) = a<br />
<br />
instance Apply (B a :& Nil b) where<br />
type Result (B a :& Nil b) = B a<br />
apply (B :& Nil) = B<br />
<br />
v1 = apply (V 1 :& Nil)<br />
f1 = apply (B :& Nil)<br />
v2 = apply (V negate :& V 1 :& Nil)<br />
f3 = apply (V negate :& B :& Nil)<br />
v3 = apply (V f3 :& V 1 :& Nil)<br />
</haskell><br />
<br />
[[User:Beelsebob|Beelsebob]] 13:04, 14 May 2009 (UTC)<br />
<br />
'''To Beelsebob''': I'm afraid the code does not account for the most<br />
interesting case: a function that takes a dynamic value and returns<br />
a static result. So you need to deal with functions of the type<br />
V a -> B b or B a -> V b. The literature on partial evaluation<br />
describes this issue in detail. Our tagless-final paper (Sec 4.2 of<br />
the the journal version, Delaying binding-time analysis) has a short<br />
explanation, too.<br />
<br />
--------------------------------------<br />
<br />
End of section 2.2, I think "cons :: a -> [b] -> [ResTy a b]" should be "cons :: a -> [b] -> ResTy a b"<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 15:28, 14 May 2009 (UTC)<br />
<br />
<br />
--------------------------------------<br />
<br />
End of page 19 with footnote 9. I could not simply copy and paste the URL because of a stray space after the '-' in http://okmij.org/ftp/Haskell/keyword- arguments.lhs<br />
<br />
[[User:ChrisKuklewicz|ChrisKuklewicz]] 16:08, 14 May 2009 (UTC)<br />
<br />
<br />
'''To Chris Kuklewicz''', regarding the problem with footnote 9. That is an<br />
odd problem that I could not reproduce. It seems xpdf lets me cut<br />
and paste the URL in question without introducing stray spaces. BTW,<br />
the type was correct, as Ryan Ingram described. We have implemented<br />
his suggestion so to remove the confusion.<br />
<br />
--------------------------------------<br />
<br />
Typo "Mounier" --> "Monnier"<br />
<br />
[[User:Tschrijvers|Tom Schrijvers]] 11:11, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Contrary to what the introductions say, polymorphism over type constructors was not part of Haskell from the beginning. They were only introduced after Mark Jones showed how to do it in Gofer.<br />
<br />
[[User:Augustss|Augustss]] 14:30, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
Why do you say "Obviously, we want to declare algebraic data kinds, ..."?<br />
What's obvious about that? Many of us think that's the wrong way, and you should instead provide a way to lift ordinary data type to the kind level.<br />
<br />
[[User:Augustss|Augustss]] 15:36, 15 May 2009 (UTC)<br />
<br />
--------------------------------------<br />
<br />
I was really fascinated by section 5.2 where you track state in the types using a parameterized monad. However, the example code you use is rather underwhelming since it can be implemented by much simpler means. If there's only a fixed number of locks then they can be tracked using a fixed tuple and the whole type functions business is a bit superfluous (albeit still nice). To really reap the benefits of the machinery you set up you ought to have a function for creating new locks dynamically. Here's an example of how it can be done:<br />
<haskell><br />
type family Length p<br />
type instance Length Nil = Zero<br />
type instance Length (Cons l p) = Succ (Length p)<br />
<br />
type family NewLock p<br />
type instance NewLock Nil = Cons Unlocked Nil<br />
type instance NewLock (Cons l p) = Cons l (NewLock p)<br />
<br />
newLock :: Nat (Length p) =><br />
LockM p (NewLock p) (Lock (Length p))<br />
newLock = LockM (return mkLock)<br />
</haskell><br />
<br />
In order for this to work nicely we need a new run function as well. I've used an ordinary type class to check that all locks are unlocked, since this really is a predicate on the state and not a function. <br />
<br />
<haskell><br />
class AllUnlocked a<br />
<br />
instance AllUnlocked Nil<br />
instance AllUnlocked p => AllUnlocked (Cons Unlocked p)<br />
<br />
runNew :: AllUnlocked locks => LockM Nil locks a -> IO a<br />
runNew = unLockM<br />
</haskell><br />
<br />
I think the section becomes more convincing if you add dynamic creation of locks. Not to mention the increased sex appeal :-)<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)<br />
<br />
'''To Josef Svenningsson''': indeed the variable number of locks would have<br />
been sexier but it creates the problem of locks `leaking' out of scope<br />
(e.g., returned as the result of runNew and then used within another<br />
runNew computation, with disastrous results). In short, we need<br />
regions. Chung-chieh Shan and I have indeed implemented such a system,<br />
with a parameterized monad to track the state of the variable number of<br />
resources (file handles in our case). Please see Sec 6 of our<br />
Lightweight Monadic Regions paper. We used functional dependencies for<br />
type functions. Replacing functional dependencies with type functions<br />
is straightforward. Yet the staggering complexity of the code in Sec 6<br />
will remain. I'm afraid this makes the example too complex for this<br />
paper; rather than attracting users to type functions we would scare<br />
all of them away.<br />
--------------------------------------<br />
<br />
It would be very nice if you published a bundle or repository somewhere containing the Haskell source from the paper. At the very least it would be nice with a comment on which version of GHC one should have and what flags are required. The reason I'm asking is that I had a bit of trouble with this. For instance, just saying {-# LANGUAGE TypeFamilies #-} didn't enable type equality constraints in the parser. I had to add ScopedTypeVariables which felt rather arbitrary.<br />
<br />
[[User:Josef|Josef]] 16:58, 25 May 2009 (UTC)</div>Nrhttps://wiki.haskell.org/index.php?title=GHC/Type_families&diff=33894GHC/Type families2010-03-01T20:34:00Z<p>Nr: correction</p>
<hr />
<div>[[Category:GHC|Indexed types]]<br />
<br />
== What are type families? ==<br />
<br />
Indexed type families, or type families for short, are type constructors that represent ''sets of types.'' Set members are denoted by supplying the type family constructor with type parameters, which are called ''type indices''. The difference between vanilla parametrised type constructors and family constructors is much like between parametrically polymorphic functions and (ad-hoc polymorphic) methods of type classes. Parametric polymorphic functions behave the same at all type instances, whereas class methods can change their behaviour in dependence on the class type parameters. Similarly, vanilla type constructors imply the same data representation for all type instances, but family constructors can have varying representation types for varying type indices.<br />
<br />
A tutorial paper that gives a number of examples of programming with type families is "[[Simonpj/Talk:FunWithTypeFuns|Fun with type functions]]" (2009).<br />
<br />
The rest of this page gives a more precise description of type families. Indexed type families come in two flavours: ''data families'' and ''type synonym families''. They are the indexed family variants of algebraic data types and type synonyms, respectively. The instances of data families can be data types and newtypes.<br />
<br />
== Type families in GHC ==<br />
<br />
Indexed type families are a new GHC extension to facilitate type-level programming. Type families are a generalisation of [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html associated data types] and [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html associated type synonyms], and are described in a [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html recent ICFP paper]. They essentially provide type-indexed data types and named functions on types, which are useful for generic programming and highly parameterised library interfaces as well as interfaces with enhanced static information, much like dependent types. They might also be regarded as an alternative to functional dependencies, but provide a more functional style of type-level programming than the relational style of functional dependencies.<br />
<br />
== What do I need to use type families? ==<br />
<br />
The first stable release of GHC that properly supports type families is 6.10.1. (An early partial implementation was part of the 6.8 release, but its use is deprecated.) Please [http://hackage.haskell.org/trac/ghc/query?status=new&status=assigned&status=reopened&group=priority&type=bug&order=id&desc=1 report bugs] via the GHC bug tracker, ideally accompanied by a small example program that demonstrates the problem. Use the [mailto:glasgow-haskell-users@haskell.org GHC mailing list] for questions or for a discussion of this language extension and its description on this wiki page.<br />
<br />
== An associated data type example ==<br />
<br />
As an example, consider Ralf Hinze's [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 generalised tries], a form of generic finite maps. <br />
<br />
=== The class declaration ===<br />
<br />
We define a type class whose instances are the types that we can use as keys in our generic maps:<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
empty :: GMap k v<br />
lookup :: k -> GMap k v -> Maybe v<br />
insert :: k -> v -> GMap k v -> GMap k v<br />
</haskell><br />
The interesting part is the ''associated data family'' declaration of the class. It gives a [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-families.html#data-family-declarations ''kind signature''] (here <hask>* -> *</hask>) for the associated data type <hask>GMap k</hask> - analog to how methods receive a type signature in a class declaration.<br />
<br />
What it is important to notice is that the first parameter of the associated type <hask>GMap</hask> coincides with the class parameter of <hask>GMapKey</hask>. This indicates that also in all instances of the class, the instances of the associated data type need to have their first argument match up with the instance type. In general, the type arguments of an associated type can be a subset of the class parameters (in a multi-parameter type class) and they can appear in any order, possibly in an order other than in the class head. The latter can be useful if the associated data type is partially applied in some contexts.<br />
<br />
The second important point is that as <hask>GMap k</hask> has kind <hask>* -> *</hask> and <hask>k</hask> (implicitly) has kind <hask>*</hask>, the type constructor <hask>GMap</hask> (without an argument) has kind <hask>* -> * -> *</hask>. Consequently, we see that <hask>GMap</hask> is applied to two arguments in the signatures of the methods <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>.<br />
<br />
=== An Int instance ===<br />
<br />
To use Ints as keys into generic maps, we declare an instance that simply uses <hask>Data.IntMap</hask>, thusly:<br />
<haskell><br />
instance GMapKey Int where<br />
data GMap Int v = GMapInt (Data.IntMap.IntMap v)<br />
empty = GMapInt Data.IntMap.empty<br />
lookup k (GMapInt m) = Data.IntMap.lookup k m<br />
insert k v (GMapInt m) = GMapInt (Data.IntMap.insert k v m)<br />
</haskell><br />
The <hask>Int</hask> instance of the associated data type <hask>GMap</hask> needs to have both of its parameters, but as only the first one corresponds to a class parameter, the second needs to be a type variable (here <hask>v</hask>). As mentioned before, any associated type parameter that corresponds to a class parameter must be identical to the class parameter in each instance. The right hand side of the associated data declaration is like that of any other data type.<br />
<br />
NB: At the moment, GADT syntax is not allowed for associated data types (or other indexed types). This is not a fundamental limitation, but just a shortcoming of the current implementation, which we expect to lift in the future.<br />
<br />
As an exercise, implement an instance for <hask>Char</hask> that maps back to the <hask>Int</hask> instance using the conversion functions <hask>Char.ord</hask> and <hask>Char.chr</hask>.<br />
<br />
=== A unit instance ===<br />
<br />
Generic definitions, apart from elementary types, typically cover units, products, and sums. We start here with the unit instance for <hask>GMap</hask>:<br />
<haskell><br />
instance GMapKey () where<br />
data GMap () v = GMapUnit (Maybe v)<br />
empty = GMapUnit Nothing<br />
lookup () (GMapUnit v) = v<br />
insert () v (GMapUnit _) = GMapUnit $ Just v<br />
</haskell><br />
For unit, the map is just a <hask>Maybe</hask> value.<br />
<br />
=== Product and sum instances ===<br />
<br />
Next, let us define the instances for pairs and sums (i.e., <hask>Either</hask>):<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (a, b) where<br />
data GMap (a, b) v = GMapPair (GMap a (GMap b v))<br />
empty = GMapPair empty<br />
lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b <br />
insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of<br />
Nothing -> insert a (insert b v empty) gm<br />
Just gm2 -> insert a (insert b v gm2 ) gm<br />
<br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
empty = GMapEither empty empty<br />
lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1<br />
lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2<br />
insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2<br />
insert (Right b) v (GMapEither gm1 gm2) = GMapEither gm1 (insert b v gm2)<br />
</haskell><br />
If you find this code algorithmically surprising, I'd suggest to have a look at [http://www.informatik.uni-bonn.de/~ralf/publications.html#J4 Ralf Hinze's paper]. The only novelty concerning associated types, in these two instances, is that the instances have a context <hask>(GMapKey a, GMapKey b)</hask>. Consequently, the right hand sides of the associated type declarations can use <hask>GMap</hask> recursively at the key types <hask>a</hask> and <hask>b</hask> - not unlike the method definitions use the class methods recursively at the types for which the class is given in the instance context.<br />
<br />
=== Using a generic map ===<br />
<br />
Finally, some code building and querying a generic map:<br />
<haskell><br />
myGMap :: GMap (Int, Either Char ()) String<br />
myGMap = insert (5, Left 'c') "(5, Left 'c')" $<br />
insert (4, Right ()) "(4, Right ())" $<br />
insert (5, Right ()) "This is the one!" $<br />
insert (5, Right ()) "This is the two!" $<br />
insert (6, Right ()) "(6, Right ())" $<br />
insert (5, Left 'a') "(5, Left 'a')" $<br />
empty<br />
main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap<br />
</haskell><br />
<br />
=== Download the code ===<br />
<br />
If you want to play with this example without copying it off the wiki, just download the [http://darcs.haskell.org/testsuite/tests/ghc-regress/indexed-types/should_run/GMapAssoc.hs source code for <hask>GMap</hask>] from GHC's test suite.<br />
<br />
== Detailed definition of data families ==<br />
<br />
Data families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated types). The former is the more general variant, as it lacks the requirement for the type-indices to coincide with the class parameters. However, the latter can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed data families are introduced by a signature, such as <br />
<haskell><br />
data family GMap k :: * -> *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard data declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
data family Array e<br />
</haskell><br />
Named arguments can also be given explicit kind signatures if needed. Just as with [http://www.haskell.org/ghc/docs/latest/html/users_guide/gadt.html GADT declarations] named arguments are entirely optional, so that we can declare <hask>Array</hask> alternatively with<br />
<haskell><br />
data family Array :: * -> *<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a data family is declared as part of a type class, we drop the <hask>family</hask> keyword. The <hask>GMap</hask> declaration takes the following form<br />
<haskell><br />
class GMapKey k where<br />
data GMap k :: * -> *<br />
...<br />
</haskell><br />
In contrast to toplevel declarations, named arguments must be used for all type parameters that are to be used as type-indices. Moreover, the argument names must be class parameters. Each class parameter may only be used at most once per associated type, but some may be omitted and they may be in an order other than in the class head. In other words: '''the named type parameters of the data declaration must be a permutation of a subset of the class variables'''. <br />
<br />
Example is admissible:<br />
<haskell><br />
class C a b c where { data T c a :: * } -- OK<br />
class C a b c where { data T a a :: * } -- Bad: repeated variable<br />
class D a where { data T a x :: * } -- Bad: x is not a class variable<br />
class D a where { data T a :: * -> * } -- OK<br />
</haskell><br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of data and newtype families are very similar to standard data and newtype declarations. The only two differences are that the keyword <hask>data</hask> or <hask>newtype</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types, but may not contain forall types or type synonym families. However, data families are generally allowed in type parameters, and type synonyms are allowed as long as they are fully applied and expand to a type that is itself admissible - exactly as this is required for occurrences of type synonyms in class instance parameters. For example, the <hask>Either</hask> instance for <hask>GMap</hask> is<br />
<haskell><br />
data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)<br />
</haskell><br />
In this example, the declaration has only one variant. In general, it can be any number.<br />
<br />
Data and newtype instance declarations are only legit when an appropriate family declaration is in scope - just like class instances require the class declaration to be visible. Moreover, each instance declaration has to conform to the kind determined by its family declaration. This implies that the number of parameters of an instance declaration matches the arity determined by the kind of the family. Although all data families are declared with the <hask>data</hask> keyword, instances can be either <hask>data</hask> or <hask>newtype</hask>s, or a mix of both.<br />
<br />
Even if type families are defined as toplevel declarations, functions that perform different computations for different family instances still need to be defined as methods of type classes. In particular, the following is not possible:<br />
<haskell><br />
data family T a<br />
data instance T Int = A<br />
data instance T Char = B<br />
nonsense :: T a -> Int<br />
nonsense A = 1 -- WRONG: These two equations together...<br />
nonsense B = 2 -- ...will produce a type error.<br />
</haskell><br />
Given the functionality provided by GADTs (Generalised Algebraic Data Types), it might seem as if a definition, such as the above, should be feasible. However, type families - in contrast to GADTs - are ''open''; i.e., new instances can always be added, possibly in other modules. Supporting pattern matching across different data instances would require a form of extensible case construct.<br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>Either</hask> instance for <hask>GMap</hask> becomes:<br />
<haskell><br />
instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where<br />
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indices corresponding to class parameters must be identical to the type given in the instance head; here this is the first argument of <hask>GMap</hask>, namely <hask>Either a b</hask>, which coincides with the only class parameter. Any parameters to the family constructor that do not correspond to class parameters, need to be variables in every instance; here this is the variable <hask>v</hask>.<br />
<br />
Instances for an associated family can only appear as part of instance declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Scoping of class parameters ====<br />
<br />
In the case of multi-parameter type classes, the visibility of class parameters in the right-hand side of associated family instances depends ''solely'' on the parameters of the data family. As an example, consider the simple class declaration<br />
<haskell><br />
class C a b where<br />
data T a<br />
</haskell><br />
Only one of the two class parameters is a parameter to the data family. Hence, the following instance declaration is invalid:<br />
<haskell><br />
instance C [c] d where<br />
data T [c] = MkT (c, d) -- WRONG!! 'd' is not in scope<br />
</haskell><br />
Here, the right-hand side of the data instance mentions the type variable <hask>d</hask> that does not occur in its left-hand side. We cannot admit such data instances as they would compromise type safety.<br />
<br />
==== Type class instances of family instances ====<br />
<br />
Type class instances of instances of data families can be defined as usual, and in particular data instance declarations can have <hask>deriving</hask> clauses. For example, we can write<br />
<haskell><br />
data GMap () v = GMapUnit (Maybe v)<br />
deriving Show<br />
</haskell><br />
which implicitly defines an instance of the form<br />
<haskell><br />
instance Show v => Show (GMap () v) where ...<br />
</haskell><br />
<br />
Note that class instances are always for particular ''instances'' of a data family and never for an entire family as a whole. This is for essentially the same reasons that we cannot define a toplevel function that performs pattern matching on the data constructors of ''different'' instances of a single type family. It would require a form of extensible case construct.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a data family used in a single program may not overlap at all, independent of whether they are associated or not. In contrast to type class instances, this is not only a matter of consistency, but one of type safety.<br />
<br />
=== Import and export ===<br />
<br />
The association of data constructors with type families is more dynamic than that is the case with standard data and newtype declarations. In the standard case, the notation <hask>T(..)</hask> in an import or export list denotes the type constructor and all the data constructors introduced in its declaration. However, a family declaration never introduces any data constructors; instead, data constructors are introduced by family instances. As a result, which data constructors are associated with a type family depends on the currently visible instance declarations for that family. Consequently, an import or export item of the form <hask>T(..)</hask> denotes the family constructor and all currently visible data constructors - in the case of an export item, these may be either imported or defined in the current module. The treatment of import and export items that explicitly list data constructors, such as <hask>GMap(GMapEither)</hask>, is analogous.<br />
<br />
==== Associated families ====<br />
<br />
As expected, an import or export item of the form <hask>C(..)</hask> denotes all of the class' methods and associated types. However, when associated types are explicitly listed as subitems of a class, we need some new syntax, as uppercase identifiers as subitems are usually data constructors, not type constructors. To clarify that we denote types here, each associated type name needs to be prefixed by the keyword <hask>type</hask>. So for example, when explicitly listing the components of the <hask>GMapKey</hask> class, we write <hask>GMapKey(type GMap, empty, lookup, insert)</hask>.<br />
<br />
==== Examples ====<br />
<br />
Assuming our running <hask>GMapKey</hask> class example, let us look at some export lists and their meaning:<br />
<br />
* <hask>module GMap (GMapKey) where...</hask>: Exports just the class name.<br />
* <hask>module GMap (GMapKey(..)) where...</hask>: Exports the class, the associated type <hask>GMap</hask> and the member functions <hask>empty</hask>, <hask>lookup</hask>, and <hask>insert</hask>. None of the data constructors is exported.<br />
* <hask>module GMap (GMapKey(..), GMap(..)) where...</hask>: As before, but also exports all the data constructors <hask>GMapInt</hask>, <hask>GMapChar</hask>, <hask>GMapUnit</hask>, <hask>GMapPair</hask>, and <hask>GMapEither</hask>.<br />
* <hask>module GMap (GMapKey(empty, lookup, insert), GMap(..)) where...</hask>: As before.<br />
* <hask>module GMap (GMapKey, empty, lookup, insert, GMap(..)) where...</hask>: As before.<br />
<br />
Finally, you can write <hask>GMapKey(type GMap)</hask> to denote both the class <hask>GMapKey</hask> as well as its associated type <hask>GMap</hask>. However, you cannot write <hask>GMapKey(type GMap(..))</hask> &mdash; i.e., sub-component specifications cannot be nested. To specify <hask>GMap</hask>'s data constructors, you have to list it separately.<br />
<br />
==== Instances ====<br />
<br />
Family instances are implicitly exported, just like class instances. However, this applies only to the heads of instances, not to the data constructors an instance defines.<br />
<br />
== An associated type synonym example ==<br />
<br />
Type synonym families are an alternative to functional dependencies, which makes functional dependency examples well suited to introduce type synonym families. In fact, type families are a more functional way to express the same as functional dependencies (despite the name!), as they replace the relational notation of functional dependencies by an expression-oriented notation; i.e., functions on types are really represented by functions and not relations.<br />
<br />
=== The <hask>class</hask> declaration ===<br />
<br />
Here's an example from Mark Jones' seminal paper on functional dependencies:<br />
<haskell><br />
class Collects e ce | ce -> e where<br />
empty :: ce<br />
insert :: e -> ce -> ce<br />
member :: e -> ce -> Bool<br />
toList :: ce -> [e]<br />
</haskell><br />
<br />
With associated type synonyms we can write this as<br />
<haskell><br />
class Collects ce where<br />
type Elem ce<br />
empty :: ce<br />
insert :: Elem ce -> ce -> ce<br />
member :: Elem ce -> ce -> Bool<br />
toList :: ce -> [Elem ce]<br />
</haskell><br />
Instead of the multi-parameter type class, we use a single parameter class, and the parameter <hask>e</hask><br />
turned into an associated type synonym <hask>Elem ce</hask>.<br />
<br />
=== An <hask>instance</hask>===<br />
<br />
Instances change correspondingly. An instance of the two-parameter class<br />
<haskell><br />
instance Eq e => Collects e [e] where<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
becomes an instance of a single-parameter class, where the dependent type parameter turns into an associated type instance declaration:<br />
<haskell><br />
instance Eq e => Collects [e] where<br />
type Elem [e] = e<br />
empty = []<br />
insert e l = (e:l)<br />
member e [] = False<br />
member e (x:xs) <br />
| e == x = True<br />
| otherwise = member e xs<br />
toList l = l<br />
</haskell><br />
<br />
=== Using generic collections ===<br />
<br />
With Functional Dependencies the code would be:<br />
<haskell><br />
sumCollects :: (Collects e c1, Collects e c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
In contrast, with associated type synonyms, we get:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
sumCollects c1 c2 = foldr insert c2 (toList c1)<br />
</haskell><br />
<br />
== Detailed definition of type synonym families ==<br />
<br />
Type families appear in two flavours: (1) they can be defined on the toplevel or (2) they can appear inside type classes (in which case they are known as associated type synonyms). The former is the more general variant, as it lacks the requirement for the type-indices to coincide with the class parameters. However, the latter can lead to more clearly structured code and compiler warnings if some type instances were - possibly accidentally - omitted. In the following, we always discuss the general toplevel form first and then cover the additional constraints placed on associated types.<br />
<br />
=== Family declarations ===<br />
<br />
Indexed type families are introduced by a signature, such as <br />
<haskell><br />
type family Elem c :: *<br />
</haskell><br />
The special <hask>family</hask> distinguishes family from standard type declarations. The result kind annotation is optional and, as usual, defaults to <hask>*</hask> if omitted. An example is<br />
<haskell><br />
type family Elem c<br />
</haskell><br />
Parameters can also be given explicit kind signatures if needed. We call the number of parameters in a type family declaration, the family's arity, and all applications of a type family must be fully saturated w.r.t. to that arity. This requirement is unlike ordinary type synonyms and it implies that the kind of a type family is not sufficient to determine a family's arity, and hence in general, also insufficient to determine whether a type family application is well formed. As an example, consider the following declaration:<br />
<haskell><br />
type family F a b :: * -> * -- F's arity is 2, <br />
-- although its overall kind is * -> * -> * -> *<br />
</haskell><br />
Given this declaration the following are examples of well-formed and malformed types:<br />
<haskell><br />
F Char [Int] -- OK! Kind: * -> *<br />
F Char [Int] Bool -- OK! Kind: *<br />
F IO Bool -- WRONG: kind mismatch in the first argument<br />
F Bool -- WRONG: unsaturated application<br />
</haskell><br />
<br />
==== Associated family declarations ====<br />
<br />
When a type family is declared as part of a type class, we drop the <hask>family</hask> special. The <hask>Elem</hask> declaration takes the following form<br />
<haskell><br />
class Collects ce where<br />
type Elem ce :: *<br />
...<br />
</haskell><br />
Exactly as in the case of an associated data declaration, '''the named type parameters must be a permutation of a subset of the class parameters'''. Examples<br />
<haskell><br />
class C a b c where { type T c a :: * } -- OK<br />
class D a where { type T a x :: * } -- No: x is not a class parameter<br />
class D a where { type T a :: * -> * } -- OK<br />
</haskell><br />
<br />
=== Instance declarations ===<br />
<br />
Instance declarations of type families are very similar to standard type synonym declarations. The only two differences are that the keyword <hask>type</hask> is followed by <hask>instance</hask> and that some or all of the type arguments can be non-variable types, but may not contain forall types or type synonym families. However, data families are generally allowed, and type synonyms are allowed as long as they are fully applied and expand to a type that is admissible - these are the exact same requirements as for data instances. For example, the <hask>[e]</hask> instance for <hask>Elem</hask> is<br />
<haskell><br />
type instance Elem [e] = e<br />
</haskell><br />
<br />
A type family instance declaration must satisfy the following rules:<br />
* An appropriate family declaration is in scope - just like class instances require the class declaration to be visible. <br />
* The instance declaration conforms to the kind determined by its family declaration<br />
* The number of type parameters in an instance declaration matches the number of type parameters in the family declaration.<br />
* The right-hand side of a type instance must be a monotype (i.e., it may not include foralls) and after the expansion of all saturated vanilla type synonyms, no synonyms, except family synonyms may remain.<br />
<br />
Here are some examples of admissible and illegal type instances:<br />
<haskell><br />
type family F a :: *<br />
type instance F [Int] = Int -- OK!<br />
type instance F String = Char -- OK!<br />
type instance F (F a) = a -- WRONG: type parameter mentions a type family<br />
type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter<br />
type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type<br />
<br />
type family G a b :: * -> *<br />
type instance G Int = (,) -- WRONG: must be two type parameters<br />
type instance G Int Char Float = Double -- WRONG: must be two type parameters<br />
</haskell><br />
<br />
==== Associated type instances ====<br />
<br />
When an associated family instance is declared within a type class instance, we drop the <hask>instance</hask> keyword in the family instance. So, the <hask>[e]</hask> instance for <hask>Elem</hask> becomes:<br />
<haskell><br />
instance (Eq (Elem [e])) => Collects ([e]) where<br />
type Elem [e] = e<br />
...<br />
</haskell><br />
The most important point about associated family instances is that the type indexes corresponding to class parameters must be identical to the type given in the instance head; here this is <hask>[e]</hask>, which coincides with the only class parameter.<br />
<br />
Instances for an associated family can only appear as part of instance declarations of the class in which the family was declared - just as with the equations of the methods of a class. Also in correspondence to how methods are handled, declarations of associated types can be omitted in class instances. If an associated family instance is omitted, the corresponding instance type is not inhabited; i.e., only diverging expressions, such as <hask>undefined</hask>, can assume the type.<br />
<br />
==== Overlap ====<br />
<br />
The instance declarations of a type family used in a single program may only overlap if the right-hand sides of the overlapping instances coincide for the overlapping types. More formally, two instance declarations overlap if there is a substitution that makes the left-hand sides of the instances syntactically the same. Whenever that is the case, the right-hand sides of the instances must also be syntactically equal under the same substitution. This condition is independent of whether the type family is associated or not, and it is not only a matter of consistency, but one of type safety.<br />
<br />
Here are two examples to illustrate the condition under which overlap is permitted.<br />
<haskell><br />
type instance F (a, Int) = [a]<br />
type instance F (Int, b) = [b] -- overlap permitted<br />
<br />
type instance G (a, Int) = [a]<br />
type instance G (Char, a) = [a] -- ILLEGAL overlap, as [Char] /= [Int]<br />
</haskell><br />
<br />
==== Decidability ====<br />
<br />
In order to guarantee that type inference in the presence of type families is decidable, we need to place a number of additional restrictions on the formation of type instance declarations (c.f., Definition 5 (Relaxed Conditions) of [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking with Open Type Functions]). Instance declarations have the general form<br />
<haskell><br />
type instance F t1 .. tn = t<br />
</haskell><br />
where we require that for every type family application <hask>(G s1 .. sm)</hask> in <hask>t</hask>, <br />
# <hask>s1 .. sm</hask> do not contain any type family constructors,<br />
# the total number of symbols (data type constructors and type variables) in <hask>s1 .. sm</hask> is strictly smaller than in <hask>t1 .. tn</hask>, and<br />
# for every type variable <hask>a</hask>, <hask>a</hask> occurs in <hask>s1 .. sm</hask> at most as often as in <hask>t1 .. tn</hask>.<br />
These restrictions are easily verified and ensure termination of type inference. However, they are not sufficient to guarantee completeness of type inference in the presence of, so called, ''loopy equalities'', such as <hask>a ~ [F a]</hask>, where a recursive occurrence of a type variable is underneath a family application and data constructor application - see the above mentioned paper for details. <br />
<br />
If the option <tt>-XUndecidableInstances</tt> is passed to the compiler, the above restrictions are not enforced and it is on the programmer to ensure termination of the normalisation of type families during type inference.<br />
<br />
=== Equality constraints ===<br />
<br />
Type context can include equality constraints of the form <hask>t1 ~ t2</hask>, which denote that the types <hask>t1</hask> and <hask>t2</hask> need to be the same. In the presence of type families, whether two types are equal cannot generally be decided locally. Hence, the contexts of function signatures may include equality constraints, as in the following example:<br />
<haskell><br />
sumCollects :: (Collects c1, Collects c2, Elem c1 ~ Elem c2) => c1 -> c2 -> c2<br />
</haskell><br />
where we require that the element type of <hask>c1</hask> and <hask>c2</hask> are the same. In general, the types <hask>t1</hask> and <hask>t2</hask> of an equality constraint may be arbitrary monotypes; i.e., they may not contain any quantifiers, independent of whether higher-rank types are otherwise enabled.<br />
<br />
Equality constraints can also appear in class and instance contexts. The former enable a simple translation of programs using functional dependencies into programs using family synonyms instead. The general idea is to rewrite a class declaration of the form<br />
<haskell><br />
class C a b | a -> b<br />
</haskell><br />
to<br />
<haskell><br />
class (F a ~ b) => C a b where<br />
type F a<br />
</haskell><br />
That is, we represent every functional dependency (FD) <hask>a1 .. an -> b</hask> by an FD type family <hask>F a1 .. an</hask> and a superclass context equality <hask>F a1 .. an ~ b</hask>, essentially giving a name to the functional dependency. In class instances, we define the type instances of FD families in accordance with the class head. Method signatures are not affected by that process.<br />
<br />
NB: Equalities in superclass contexts are not fully implemented in the GHC 6.10 branch.<br />
<br />
== Frequently asked questions ==<br />
<br />
=== Injectivity, type inference, and ambiguity ===<br />
<br />
A common problem is this<br />
<haskell><br />
type family F a<br />
<br />
f :: F a -> F a<br />
f = undefined<br />
<br />
g :: F Int -> F Int<br />
g x = f x<br />
</haskell><br />
The compiler complains about the definition of <tt>g</tt> saying<br />
<haskell><br />
Couldn't match expected type `F Int' against inferred type `F a1'<br />
</haskell><br />
In type-checking <tt>g</tt>'s right hand side GHC discovers (by instantiating f's type with a fresh type variable) that it has type <tt>F a1 -> F a1</tt> for some as-yet-unknown type <tt>a1</tt>. Now it tries to make the inferred type match <tt>g</tt>'s type signature. Well, you say, just make <haskell>a1</haskell> equal to <tt>Int</tt> and you are done. True, but what if there were these instance<br />
<haskell><br />
type instance F Int = Bool<br />
type instance F Char = Bool<br />
</haskell><br />
Then making <tt>a1</tt> equal to <tt>Char</tt> would ''also'' make the two types equal. Because there is more than one choice, the program is rejected.<br />
<br />
The difficulty is that the type function <tt>F</tt> need not be ''injective''; it can map two distinct types to the same type. For an injective type constructor like <tt>Maybe</tt>, if we know that <tt>Maybe t1</tt> = <tt>Maybe t2</tt>, then we know that <tt>t1</tt> = <tt>t2</tt>. But not so for non-injective type functions.<br />
<br />
The problem starts with <tt>f</tt>. Its type is ''ambiguous''; even if I know the argument and result types for <tt>f</tt>, I cannot use that to find the type at which <tt>a</tt> should be instantiated. (So arguably, <tt>f</tt> should be rejected as having an ambiguous type, and probably will be in future.) The situation is well known in type classes: <br />
<haskell><br />
bad :: (Read a, Show a) => String -> String<br />
bad x = show (read x)<br />
</haskell><br />
At a call of <tt>bad</tt> one cannot tell at what type <tt>a</tt> should be instantiated.<br />
<br />
The only solution is to avoid ambiguous types. In the type signature of a function, <br />
* Ensure that every type variable occurs in the part after the "<tt>=></tt>"<br />
* Ensure that every type variable appears at least once outside a type function call. <br />
<br />
Even then ambiguity is possible. For example:<br />
<haskell><br />
f :: F a -> [a] <br />
f = undefined<br />
<br />
g :: F b -> Int<br />
g x = length (f x)<br />
</haskell><br />
Although <tt>f</tt>'s type is unambiguous, its result type is swallowed up by <tt>length</tt>, which now makes <tt>g</tt>'s type ambiguous.<br />
<br />
== References ==<br />
<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKPM05.html Associated Types with Class.] Manuel M. T. Chakravarty, Gabriele Keller, Simon Peyton Jones, and Simon Marlow. In ''Proceedings of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL'05)'', pages 1-13, ACM Press, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/CKP05.html Associated Type Synonyms.] Manuel M. T. Chakravarty, Gabriele Keller, and Simon Peyton Jones. In ''Proceedings of The Tenth ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 241-253, 2005.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SCPD07.html System F with Type Equality Coercions.] Martin Sulzmann, Manuel M. T. Chakravarty, Simon Peyton Jones, and Kevin Donnelly. In ''Proceedings of The Third ACM SIGPLAN Workshop on Types in Language Design and Implementation'', ACM Press, 2007.<br />
* [http://www.cse.unsw.edu.au/~chak/papers/SPCS08.html Type Checking With Open Type Functions.] Tom Schrijvers, Simon Peyton-Jones, Manuel M. T. Chakravarty, Martin Sulzmann. In ''Proceedings of The 13th ACM SIGPLAN International Conference on Functional Programming'', ACM Press, pages 51-62, 2008.<br />
<br />
[[Category:Type-level programming]]<br />
[[Category:Language extension]]</div>Nrhttps://wiki.haskell.org/index.php?title=User_groups&diff=33694User groups2010-02-19T23:58:17Z<p>Nr: there's a user group in Boston!</p>
<hr />
<div>[[Category:Community]]<br />
<br />
A range of Haskell User Groups are springing up all over. Also see a [http://www.frappr.com/haskellers Map of Haskellers].<br />
<br />
== User groups ==<br />
<br />
Regular meetings in a particular geographical area. Great if you want to see and meet other Haskellers.<br />
<br />
===North America===<br />
<br />
====West Coast ====<br />
<br />
;[http://socalfp.blogspot.com/ SoCal FP Group]<br />
<br />
;[http://bayfp.org/ The Bay Area Functional Programmers group]<br />
:Meeting monthly in the San Francisco Bay area. See [http://bayfp.org/blog their blog] for more details and news of upcoming meetings.<br />
<br />
;[http://pdxfunc.org PDXfunc: Portland FP Group]<br />
:Monthly meetings of the Portland, Oregon functional programming group. Meetings occur on the second Monday of each month at 7 pm, typically in Downtown/NW Portland.<br />
<br />
;[http://www.haskell.org/pipermail/haskell-cafe/2008-February/038991.html Seattle: Northwest Functional Programming Interest Group]<br />
:a Northwest Functional Programming Interest Group in Seattle.<br />
<br />
;[http://groups.google.com/group/hugvan Vancouver, Canada: Haskell Programmers Group]<br />
:Regular informal meetings for local Haskell programmers/devotees.<br />
<br />
====East Coast====<br />
<br />
;[http://groups.google.com/group/bostonhaskell Boston Haskell Users' Group].<br />
:Meets monthly.<br />
<br />
;[http://article.gmane.org/gmane.comp.lang.haskell.cafe/21856 New York Functional Programmers Network]<br />
:Come and meet like-minded functional programmers in the New York area. The next meeting is at 6:30pm on February 26th, at Credit Suisse's offices. Paul Hudak from Yale will be giving a talk on real-time sound synthesis using Haskell. Please RSVP at the [http://lisp.meetup.com/59/ NYFPN Meetup Page].<br />
<br />
;[http://www.lisperati.com/fringedc.html FringeDC Washington]<br />
:Meetings about functional programming languages in Washington DC.<br />
<br />
====Central====<br />
<br />
;[http://leibnizdream.wordpress.com/2007/12/22/new-austin-functional-programmers-group-in-2008/ Austin Functional Programmers Group]<br />
:See the [http://groups.google.com/group/austin-fp discussion group] for more.<br />
<br />
;[http://groups.google.com/group/real-world-haskell-book-club/browse_thread/thread/3e8e59768c8c50a9 Colorado Area Haskell Study Group]<br />
<br />
;[http://groups.google.com/group/haskell-chicago Chicago Haskell User Group] — new group, had first general meeting in December 2009; meeting every other month.<br />
<br />
;[http://www.meetup.com/DenHUG/ Denver Area Haskell Users Group] -- New group with first meeting 27 Feb 2010; subsequent meetings TBA.<br />
<br />
===Australia===<br />
<br />
;[http://groups.google.com/group/fp-syd FP-SYD, the Sydney (Australia) Functional Programming group]<br />
:FP hackers in Sydney.<br />
<br />
;[http://sites.google.com/site/fpunion/ (FPU) Melbourne Functional Programming Union]<br />
:The FPU is a collective of functional programming language enthusiasts, which has been in operation since 1998. We are based at the University of Melbourne, in the Department of Computer Science and Software Engineering, but we are open to all members of the community. We meet on a regular basis for lively discussions on topics broadly associated with the declarative programming paradigm.<br />
<br />
;[http://www.meetup.com/Brisbane-Functional-Programming-Group-BFG/ Brisbane Functional Programming Group]<br />
; A group for Functional Programming with Haskell, Scala and other languages.<br />
<br />
===Europe===<br />
<br />
;[http://www.londonhug.net/ London Haskell User Group]<br />
:The first meeting of the London Haskell User Group took place on 23rd May 2007, at City University in central London<br />
<br />
''If anyone is interested in a user group in '''Cambridge, UK''' please let me know ( pocmatos@gmail.com ).''<br />
<br />
;Haskell in Leipzig<br />
:Hal, they have videos [http://iba-cg.de/haskell.html online].<br />
<br />
;[http://oasis.yi.org/oasis/HUGZ Haskell User Group Zurich]<br />
:A user group for the haskell users residing in Zurich and surroundings. It's new and still being formed.<br />
<br />
;[[IsraelHaskell]] User Group<br />
:[http://article.gmane.org/gmane.comp.lang.haskell.cafe/28877 Are getting organised].<br />
<br />
;[http://spbhug.folding-maps.org Saint-Petersburg Haskell User Group]<br />
:The next meeting will be held in April, 2008.<br />
<br />
;[[ItaloHaskell]]<br />
:We had a first meeting in August 2008 and we are planning a second one sometime during the 2008/2009 Autumn/Winter season.<br />
<br />
;[[Reykjavik Haskell User Group]] Iceland<br />
;[http://groups.google.com/group/haskell-is Currently recruiting members]<br />
<br />
;[http://groups.google.com/group/core-haskell?lnk=srg Turkey Haskell Programmer's Group]<br />
:Formed by Turkish Functional Programmers, the group began to communicate via an e-mail list opened by core.gen.tr. The first contribution is hlibev project by Aycan iRiCAN.<br />
<br />
;[http://bilfp.wikidot.com/ BILFP (Bilkent University Comp. Eng. Dept. Functional Programming Society)] Turkey <br />
:Project aims to improve people's knowledge and encourage the use of functional programming languages &mdash; especially in Turkey. Group is open to functional-programming-related discussions and establishes related presentations at Bilkent University that are open to anybody.<br />
<br />
;[[Dutch HUG]]<br />
:The Dutch HUG meets monthly in an informal setting.<br />
<br />
;[http://groups.google.com/group/fp-southwales fp-southwales], the South Wales Functional Programming User Group<br />
:Starting up in late 2009, based out of Swansea University.<br />
<br />
===South America===<br />
<br />
;[http://groups.google.com/group/hug-br HUG-BR]<br />
:Haskell Users' Group for Brasil<br />
<br />
===Asia===<br />
<br />
;[http://lisp.org.cn/en/ China Lisp User Group]<br />
:China Lisp User Group (CLUG) is the earliest founded Lisp user group in China. <br />
<br />
;[http://www.starling-software.com/en/tsac.html Tokyo Society for the Application of Currying]<br />
<br />
== Workshops/meet ups ==<br />
<br />
Less regular, and move around. Usually have a few talks from invited speakers.<br />
<br />
;[[AngloHaskell]]<br />
:AngloHaskell is a Haskell meeting held in England once a year.<br />
<br />
;[[OzHaskell]]<br />
:Australian Haskell Programmer's Group<br />
<br />
;[[AmeroHaskell]]<br />
:USAsian Haskell Programmer's Group<br />
<br />
;[http://taichi.ddns.comp.nus.edu.sg/taichiwiki/SingHaskell2007 SingHaskell]<br />
:Sing(apore)Haskell is a Haskell (and related languages) meeting in Singapore<br />
* [http://www.comp.nus.edu.sg/~sulzmann/singhaskell07/index.html slides]<br />
<br />
;[http://www.comp.mq.edu.au/~asloane/pmwiki.php/SAPLING/HomePage Sydney Area Programming Languages Interest Group]<br />
:10am-4pm, June 12, 2007. Room T5, Building E7B, Macquarie University<br />
<br />
;[http://www.cs.uu.nl/~johanj/FPDag2008/ Utrecht Functioneel Programmeren dag 2008]<br />
:11 januari 2008<br />
<br />
== Hackathons ==<br />
<br />
Getting together to squash bugs and write new stuff. For a more complete list, see [[Hackathon]].<br />
<br />
;[http://haskell.org/haskellwiki/Hac_2007 Hackathons]<br />
:Hac 07 was held January 10-12, 2007, Oxford University Computing Laboratory<br />
<br />
;[http://haskell.org/haskellwiki/HaL3 HaL3 Hackathon]<br />
:HaL3 was held Apr 19-20, 2008, Leipzig<br />
<br />
;[[Hac5]]<br />
:Hac5 was held 17-19 April 2009 in Utrecht.<br />
<br />
== Conferences ==<br />
<br />
See the [[Conferences]] page for academic workshops and conferences<br />
focusing on Haskell and related technology</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23621Boston Area Haskell Users' Group2008-10-23T03:59:15Z<p>Nr: /* Call for volunteers */</p>
<hr />
<div>[[Category:Community]]<br />
== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties<br />
If you want to volunteer, please '''visit [[Boston Area Haskell Users' Group/Volunteers|the volunteers' page]]'''<br />
<br />
At some point we may be lucky enough to have a surplus of potential presenters. In that case we may need volunteers for a selection committee. A reasonable structure might be to have a committee of three who serve staggered six-month terms. If we can't find enough presenters, those same people could try to find some. In both cases people would be volunteering to help manage the program for three meetings.</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23620Boston Area Haskell Users' Group2008-10-23T03:58:36Z<p>Nr: we'll probably need a selection committee</p>
<hr />
<div>[[Category:Community]]<br />
== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties<br />
If you want to volunteer, please visit [[Boston Area Haskell Users' Group/Volunteers|the volunteers' page]]<br />
<br />
At some point we may be lucky enough to have a surplus of potential presenters. In that case we may need volunteers for a selection committee. A reasonable structure might be to have a committee of three who serve staggered six-month terms. If we can't find enough presenters, those same people could try to find some. In both cases people would be volunteering to help manage the program for three meetings.</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group/Volunteers&diff=23619Boston Area Haskell Users' Group/Volunteers2008-10-23T03:56:00Z<p>Nr: Things you can volunteer for and those who have volunteered</p>
<hr />
<div>Please volunteer for something!<br />
<br />
== Hosting a meeting ==<br />
<br />
== Presenting at a meeting ==<br />
<br />
== Finding people to present at a meeting ==</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23618Boston Area Haskell Users' Group2008-10-23T03:54:03Z<p>Nr: </p>
<hr />
<div>[[Category:Community]]<br />
== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties<br />
If you want to volunteer, please visit [[Boston Area Haskell Users' Group/Volunteers|the volunteers' page]]</div>Nrhttps://wiki.haskell.org/index.php?title=BostonUsersGroup&diff=23617BostonUsersGroup2008-10-23T03:52:24Z<p>Nr: BostonUsersGroup moved to Boston Area Haskell Users' Group: Did not realize page title was so tightly coupled to its URL</p>
<hr />
<div>#redirect [[Boston Area Haskell Users' Group]]</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23616Boston Area Haskell Users' Group2008-10-23T03:52:24Z<p>Nr: BostonUsersGroup moved to Boston Area Haskell Users' Group</p>
<hr />
<div>== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties<br />
If you want to volunteer, please visit [[BostonUsersGroup:Volunteers|the volunteers' page]]</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23615Boston Area Haskell Users' Group2008-10-23T03:37:32Z<p>Nr: formatting</p>
<hr />
<div>== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties<br />
If you want to volunteer, please visit [[BostonUsersGroup:Volunteers|the volunteers' page]]</div>Nrhttps://wiki.haskell.org/index.php?title=Boston_Area_Haskell_Users%27_Group&diff=23614Boston Area Haskell Users' Group2008-10-23T03:35:15Z<p>Nr: Let's put on a show! (Just kidding --- proposal for Boston Area Haskell Users' Group</p>
<hr />
<div>== Purpose and Goals ==<br />
<br />
The purpose of the Boston Area Haskell Users' Group is to provide a regular forum in which area people interested in Haskell can get together, meet each other, share skills, and grow the community<br />
<br />
== Meeting Format ==<br />
<br />
The Haskell Users' Group is '''not a forum for academic talks'''. The Boston area already provides plenty of opportunities for academics to give talks. The Haskell Users' Group is a forum for '''informal interactions''' and a place where you can '''show us the code'''.<br />
<br />
The ideal meeting will include two presentations and a break:<br />
* A presentation of '''code that even a beginner will appreciate'''<br />
* A break<br />
* A presentation of '''code that will make at least some experts say Ooh! and Aah!'''<br />
Demos are also encouraged, but we want to see at least a little bit of code, please.<br />
<br />
== Planned schedule ==<br />
<br />
The group is intended to launch in January 2009 with a schedule of six meetings per year. The calendar is designed so that most meetings are scheduled at a time when people might have something new to show off.<br />
* A meeting in late January following POPL<br />
* A meeting at the end of March or the beginning of April, just after the ICFP deadline<br />
* A meeting in May after classes are out but before students and professors have dispersed for the summer<br />
* A meeting in July after the POPL deadline and perhaps just after the [http://icfpcontest.org ICFP programming contest]<br />
* A meeting in September following [http://www.icfpconference.org ICFP] and the Haskell Symposium<br />
* A meeting in November with a special emphasis on companies who may wish to recruit interns or new employees<br />
If you want to volunteer, please visit BostonUsersGroup:Volunteers<br />
<br />
== Call for volunteers ==<br />
We need volunteers<br />
* To host one of the regular meetings<br />
* To present<br />
* To twist other people's arms to present<br />
* To talk to John Hughes and learn how to organize a "jobs fair" for the November meeting<br />
* To acquire a mailing list (perhaps boston at haskell dot org) and populate it with interested parties</div>Nr