https://wiki.haskell.org/api.php?action=feedcontributions&user=Takenobu.hs&feedformat=atomHaskellWiki - User contributions [en]2024-03-28T13:29:51ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=MonadFail_Proposal&diff=63489MonadFail Proposal2020-11-07T01:15:10Z<p>Takenobu.hs: Update the hyperlink to prime wiki</p>
<hr />
<div>'''Note:''' this proposal page has been moved to [https://gitlab.haskell.org/haskell/prime/-/wikis/libraries/proposals/monad-fail the Haskell Prime Wiki]; the article below is unmaintained.<br />
<br />
<br />
== <code>MonadFail</code> proposal (MFP) ==<br />
<br />
A couple of years ago, we proposed to make <code>Applicative</code> a superclass of <code>Monad</code> which successfully killed the single most ugly thing in Haskell as of GHC 7.10.<br />
<br />
Now, it's time to tackle the other major issue with <code>Monad</code> <code>fail</code> being a part of it.<br />
<br />
You can contact me as usual via IRC/Freenode as ''quchen'', or by email to ''dluposchainsky at the email service of Google''. This file was posted on the ghc-devs@ and [http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/24910 libraries@ mailing lists], as well as on [http://www.reddit.com/r/haskell/comments/397k1a/monadfail_proposal_mfp_moving_fail_out_of_monad/ Reddit].<br />
<br />
This proposal was first posted on [https://github.com/quchen/articles/blob/master/monad_fail.md quchen's articles Github repo].<br />
<br />
=== Overview ===<br />
<br />
* '''The problem''' - reason for the proposal<br />
* '''MonadFail class''' - the solution<br />
* '''Discussion''' - explaining our design choices<br />
* '''Adapting old code''' - how to prepare current code to transition smoothly<br />
* '''Estimating the breakage''' - how much stuff we will break<br />
* '''Transitional strategy''' - how to break as little as possible while transitioning<br />
* '''Current status'''<br />
<br />
=== The problem ===<br />
<br />
Currently, the <code><-</code> symbol is unconditionally desugared as follows:<br />
<br />
<syntaxhighlight lang="haskell"><br />
do pat <- computation >>> let f pat = more<br />
more >>> f _ = fail "..."<br />
>>> in computation >>= f<br />
</syntaxhighlight><br />
<br />
The problem with this is that <code>fail</code> cannot (!) be sensibly implemented for many monads, for example <code>Either</code>, <code>State</code>, <code>IO</code>, and <code>Reader</code>. In those cases it defaults to <code>error</code> As a consequence, in current Haskell, you can not use <code>Monad</code> polymorphic code safely, because although it claims to work for all <code>Monad</code> , it might just crash on you. This kind of implicit non-totality baked into the class is ''terrible''.<br />
<br />
The goal of this proposal is adding the <code>fail</code> only when necessary and reflecting that in the type signature of the <code>do</code> block, so that it can be used safely, and more importantly, is guaranteed not to be used if the type signature does not say so.<br />
<br />
=== <code>MonadFail</code> class ===<br />
<br />
To fix this, introduce a new typeclass:<br />
<br />
<syntaxhighlight lang="haskell"><br />
class Monad m => MonadFail m where<br />
fail :: String -> m a<br />
</syntaxhighlight><br />
<br />
Desugaring can now be changed to produce this constraint when necessary. For this, we have to decide when a pattern match can not fail; if this is the case, we can omit inserting the <code>fail</code> call.<br />
<br />
The most trivial examples of unfailable patterns are of course those that match anywhere unconditionally,<br />
<br />
<syntaxhighlight lang="haskell"><br />
do x <- action >>> let f x = more<br />
more >>> in action >>= f<br />
</syntaxhighlight><br />
<br />
In particular, the programmer can assert any pattern be unfailable by making it irrefutable using a prefix tilde:<br />
<br />
<syntaxhighlight lang="haskell"><br />
do ~pat <- action >>> let f ~pat = more<br />
more >>> in action >>= f<br />
</syntaxhighlight><br />
<br />
A class of patterns that are conditionally failable are <code>newtype</code> , and single constructor <code>data</code> types, which are unfailable by themselves, but may fail if matching on their fields is done with failable patterns.<br />
<br />
<syntaxhighlight lang="haskell"><br />
data Newtype a = Newtype a<br />
<br />
-- "x" cannot fail<br />
do Newtype x <- action >>> let f (Newtype x) = more<br />
more >>> in action >>= f<br />
<br />
-- "Just x" can fail<br />
do Newtype (Just x) <- action >>> let f (Newtype (Just x)) = more<br />
more >>> f _ = fail "..."<br />
>>> in action >>= f<br />
</syntaxhighlight><br />
<br />
<code>ViewPatterns</code> are as failable as the pattern the view is matched against. Patterns like <code>(Just -> Just x)</code> should generate a <code>MonadFail</code> constraint even when it's "obvious" from the view's implementation that the pattern will always match. From an implementor's perspective, this means that only types (and their constructors) have to be looked at, not arbitrary values (like functions), which is impossible to do statically in general.<br />
<br />
<syntaxhighlight lang="haskell"><br />
do (view -> pat) <- action >>> let f (view -> pat) = more<br />
more >>> f _ = fail "..."<br />
>>> in action >>= f<br />
<br />
do (view -> ~pat) <- action >>> let f (view -> ~pat) = more<br />
more >>> in action >>= f<br />
</syntaxhighlight><br />
<br />
[Edward Kmett: `(view -> pat)` should be unfailing iff pat is unfailing.]<br />
<br />
A similar issue arises for <code>PatternSynonyms</code> which we cannot inspect during compilation sufficiently. A pattern synonym will therefore always be considered failable.<br />
<br />
<syntaxhighlight lang="haskell"><br />
do PatternSynonym x <- action >>> let f PatternSynonym x = more<br />
more >>> f _ = fail "..."<br />
>>> in action >>= f<br />
</syntaxhighlight><br />
<br />
[Edward Kmett: We have the contents of the pattern synonym available to us at the definition site. With some work we should be able to expose it enough that the compiler can see through it:<br />
<br />
<syntaxhighlight lang="haskell"><br />
pattern Foo a b = Bar a 0 b<br />
pattern Baz a b c <- Quux a b c<br />
</syntaxhighlight><br />
<br />
Both of those tell us the "real" desugaring as just another pattern we could recurse into.]<br />
<br />
=== Discussion ===<br />
<br />
* What laws should <code>fail</code> follow?<br />
** '''Left zero''': <code>∀ s f. fail s >>= f ≡ fail s</code>.<br />
** '''Right zero''': <code>∀ v s. v >> fail s ≡ fail s</code>.<br />
* What is the relationship to <code>MonadPlus</code>?<br />
** As the laws above indicate, <code>fail</code> is a close relative of <code>mzero</code>. We could suggest a default definition of <code>fail _ = mzero</code>, which shows the intended usage and effect of the <code>MonadFail</code> class.<br />
** However, we should not remove <code>fail</code> and use only <code>mzero</code> instead. <br />
*** Not all types with <code>Monad</code> instances have <code>MonadPlus</code> instances.<br />
*** Some types do use the <code>String</code> argument to <code>fail</code>. For example, a parser might fail with a message involving positional information. <code>Binary</code> uses <code>fail</code> as their only interface to fail a decoding step.<br />
*** Some types have different definitions for <code>mzero</code> and <code>fail</code>. Although <code>STM</code> is <code>MonadPlus</code> it uses the default <code>fail = error</code>. It should therefore not get a <code>MonadFail</code> instance.<br />
* Rename <code>fail</code>?<br />
** '''No.''' Old code might use <code>fail</code> explicitly and we should avoid breaking it. The Report talks about <code>fail</code> and we have a solid migration strategy that does not require a renaming.<br />
* Remove the <code>String</code> argument?<br />
** '''No.''' The <code>String</code> might help error reporting and debugging. <code>String</code> may be ugly, but it's the de facto standard for simple text in GHC. No high performance string operations are to be expected with <code>fail</code> so this breaking change would in no way be justified. Also note that explicit <code>fail</code> calls would break if we removed the argument.<br />
* How sensitive would existing code be to subtle changes in the strictness behaviour of <code>do</code> notation pattern matching?<br />
** '''It doesn't.''' The implementation does not affect strictness at all, only the desugaring step. Care must be taken when fixing warnings by making patterns irrefutable using <code>~</code> as that ''does'' affect strictness. (Cf. difference between lazy/strict State)<br />
* Do we need a class constraint (e.g. <code>Monad</code>) on <code>MonadFail</code>?<br />
** '''Yes.''' The intended use of <code>fail</code> is for desugaring <code>do</code>-notation, not generally for any <code>String -> m a</code> function. Given that goal, we would rather keep the constraints simple as <code>MonadFail m =></code> rather than the somewhat redundant <code>(Monad m, MonadFail m) =></code>.<br />
* Can we relax the class constraint from <code>Monad</code> to <code>Applicative</code>?<br />
** We don't necessarily have to choose now. Since <code>Applicative</code> is a superclass of <code>Monad</code>, it is possible to change the superclass for <code>MonadFail</code> to <code>Applicative</code> later. This will naturally require a migration period, and the name will, of course, become misleading.<br />
** For the sake of discussion, let's use the following definition:<syntaxhighlight lang="haskell">class Applicative f => ApplicativeFail f where fail :: String -> f a</syntaxhighlight><br />
** '''Pros'''<br />
*** <code>ApplicativeDo</code> is coming, and <code>fail</code> may be useful to combine pattern matching and <code>Applicative</code> code.<br />
*** If the <code>Monad</code> constraint is kept, that would force <code>Applicative</code> code with pattern matching to be <code>Monad</code> code.<br />
** '''Cons'''<br />
*** The constraints for <code>Monad</code> code using <code>fail</code> become <code>(Monad m, ApplicativeFail m) =></code> instead of the simpler <code>MonadFail m =></code>. If we expect the common use of <code>fail</code> to be in <code>Monad</code> — not <code>Applicative</code> — <code>do</code>-notation, this leaves us with more verbose constraints.<br />
** Here are alternative definitions (with names open to debate) that would allow us to keep the constraints simple:<br />
*** <syntaxhighlight lang="haskell">class Applicative f => ApplicativeFail f where failA :: String -> f a</syntaxhighlight><br />
*** <syntaxhighlight lang="haskell">class ApplicativeFail m => MonadFail m where fail :: String -> m a; fail = failA</syntaxhighlight><br />
*** Since we do not have much experience using <code>ApplicativeDo</code>, it is not yet clear that this large of a change is useful.<br />
* Which types with <code>Monad</code> instances will not have <code>MonadFail</code> instances?<br />
** <code>base</code>: <code>Either</code><br />
** <code>transformers</code>:<br />
** <code>stm</code>: <code>STM</code><br />
* What <code>MonadFail</code> instances will be created?<br />
** <code>base</code>: <code>IO</code><br />
** <code>transformers</code>:<br />
*** Proposal for an <code>Either</code> instance using <code>Monad</code> instance in <code>Control.Monad.Trans.Error</code>:<syntaxhighlight lang="haskell">instance MonadFail (Either String) where fail = Left </syntaxhighlight><br />
<br />
=== Adapting old code ===<br />
<br />
<ul><br />
<li>Help! My code is broken because of a missing <code>MonadFail</code> instance! ''Here are your options:''<br />
<ol><li>Write a <code>MonadFail</code> instance (and bring it into scope)<br />
<syntaxhighlight lang="haskell"><br />
#if !MIN_VERSION_base(4,11,0)<br />
-- Control.Monad.Fail import is redundant since GHC 8.8.1<br />
import qualified Control.Monad.Fail as Fail<br />
#endif<br />
import Control.Monad<br />
<br />
instance Monad Foo where<br />
(>>=) = <...bind impl...><br />
-- NB: <code>return</code> defaults to <code>pure</code><br />
#if !MIN_VERSION_base(4,11,0)<br />
-- Monad(fail) was removed in GHC 8.8.1<br />
fail = Fail.fail<br />
#endif<br />
<br />
instance MonadFail Foo where<br />
fail = <...fail implementation...><br />
</syntaxhighlight></li><br />
<li>Change your pattern to be irrefutable</li><br />
<li>Emulate the old behaviour by desugaring the pattern match by hand:<br />
<syntaxhighlight lang="haskell"><br />
do Left e <- foobar<br />
stuff<br />
</syntaxhighlight> becomes <syntaxhighlight lang="haskell"><br />
do x <- foobar<br />
e <- case x of<br />
Left e' -> e'<br />
Right r -> error "Pattern match failed" -- Boooo<br />
stuff<br />
</syntaxhighlight><br />
The point is you'll have to do your dirty laundry yourself now if you have a value that ''you'' know will always match, and if you don't handle the other patterns you'll get incompleteness warnings, and the compiler won't silently eat those for you.</li><br />
</ol></li><br />
<li>Help! My code is broken because you removed <code>fail</code> from <code>Monad</code> but my class defines it! ''Delete that part of the instance definition.''</li></ul><br />
<br />
=== Esimating the breakage ===<br />
<br />
Using our initial implementation, I compiled stackage-nightly, and grepped the logs for the warnings. Assuming my implementation is correct, the number of "missing <code>MonadFail</code> warnings generated is 487. Note that I filtered out <code>[]</code> <code>Maybe</code> and <code>ReadPrec</code> since those can be given a <code>MonadFail</code> instance from within GHC, and no breakage is expected from them.<br />
The build logs can be found [https://www.dropbox.com/s/knz0i979skam4zs/stackage-build.tar.xz?dl=0 here]. Search for "failable pattern" to find your way to the still pretty raw warnings.<br />
<br />
Here are some commands you might find interesting for exploring the logs:<br />
<br />
<syntaxhighlight lang="bash"><br />
# List all packages generating warnings (57 of them)<br />
grep "is used in the context" '' | \<br />
grep -v '(‘\[|Maybe|ReadPrec)' | \<br />
perl -pe 's#^(.'')\.log.''$#\1#' | \<br />
uniq -u<br />
<br />
# Histogram of the breaking contexts (mostly IO and parsers)<br />
grep "is used in the context" '' | \<br />
grep -v '(‘\[|Maybe|ReadPrec)' | \<br />
perl -pe 's#^.''in the context ‘([^ ]+).''$#\1#' | \<br />
sort | \<br />
uniq -c | \<br />
sort -rg<br />
</syntaxhighlight><br />
<br />
=== Transitional strategy ===<br />
<br />
The roadmap is similar to the [https://github.com/quchen/articles/blob/master/applicative_monad.md AMP], the main difference being that since <code>MonadFail</code> does not exist yet, we have to introduce new functionality and then switch to it.<br />
<br />
<ol><br />
<li>GHC 8.0 / base-4.9<br />
<ul><br />
<li>Add module <code>Control.Monad.Fail</code> with new class <code>MonadFail(fail)</code> so people can start writing instances for it. <code>Control.Monad</code> only re-exports the class <code>MonadFail</code> but not its <code>fail</code> method. NB: At this point, <code>Control.Monad.Fail.fail</code> clashes with <code>Prelude.fail</code> and <code>Control.Monad.fail</code>.</li><br />
<li>Add a language extension <code>-XMonadFailDesugaring</code> that changes desugaring to use <code>MonadFail(fail)</code> instead of <code>Monad(fail)</code> This has the effect that typechecking will infer a <code>MonadFail</code> constraint for <code>do</code> blocks with failable patterns, just as it is planned to do when the entire thing is done.</li><br />
<li>Add a warning when a <code>do</code> block that contains a failable pattern is desugared, but there is no <code>MonadFail</code> instance in scope: "Please add the instance or change your pattern matching." Add a flag to control whether this warning appears, but leave it off by default.</li><br />
<li>Add a warning when an instance implements the <code>fail</code> function (or when <code>fail</code> is imported as a method of <code>Monad</code> , as it will be removed from the <code>Monad</code> class in the future. (See also [https://ghc.haskell.org/trac/ghc/ticket/10071 GHC #10071]). Leave it off by default.</li><br />
</ul><br />
</li><br />
<li>GHC 8.4<br />
<ul><br />
<li>Turn on the warning about missing <code>MonadFail</code> instances that we added in 8.0 by default.</li><br />
</ul><br />
</li><br />
<li>GHC 8.6<br />
<ul><br />
<li>Switch <code>-XMonadFailDesugaring</code> on by default.</li><br />
<li>Warnings are still issued if the desugaring extension has been explicitly disabled.</li><br />
<li>Turn on the warning about explicit definition of `fail` in Monad that we added in 8.0 by default.</li><br />
</ul><br />
</li><br />
<li>GHC 8.8<br />
<ul><br />
<li>Remove <code>-XMonadFailDesugaring</code> leaving its effects on at all times.</li><br />
<li>Remove <code>fail</code> from <code>Monad</code></li><br />
<li>Instead, re-export <code>Control.Monad.Fail.fail</code> as <code>Prelude.fail</code> and <code>Control.Monad.fail</code></li><br />
<li><code>Control.Monad.Fail</code> is now a redundant module that can be considered deprecated.</li><br />
</ul><br />
</li><br />
</ol><br />
<br />
=== Current status ===<br />
<br />
* [https://wiki.haskell.org/ZuriHac2015 ZuriHac 2015 (29.5. - 31.5.)]: Franz Thoma (@fmthoma) and me (David Luposchainsky aka @quchen) started implementing the MFP in GHC.<br />
** Desugaring to the new <code>fail</code> can be controlled via a new language extension, <code>MonadFailDesugaring</code><br />
** If the language extension is turned off, a warning will be emitted for code that would break if it was enabled.<br />
** Warnings are emitted for types that ''have'' a ''MonadFail'' instance. This still needs to be fixed.<br />
** The error messages are readable, but should be more so. We're still on this.<br />
* 2015-06-09: Estimated breakage by compiling Stackage. Smaller than expected.<br />
* 2015-06-09 (late): Published. People seem to like the idea, with a couple of pain points remaining.<br />
* 2015-06-16: [https://github.com/quchen/articles/blob/master/monad_fail_update1.md Update 1 posted.]<br />
* 2015-09-18: [https://phabricator.haskell.org/D1248 Patch nearly finished. Some nontrivial tests still fail.]</div>Takenobu.hshttps://wiki.haskell.org/index.php?title=Haskell_programming_tips/Discussion&diff=63488Haskell programming tips/Discussion2020-11-07T01:13:03Z<p>Takenobu.hs: Update the hyperlink to prime wiki</p>
<hr />
<div>== About ==<br />
This page is meant for discussions about ThingsToAvoid, as consensus seems to be difficult to reach, and it'd be nice if newbies wouldn't bump into all kinds of Holy Wars during their first day of using Haskell ;)<br />
<br />
You may want to add your name to your comments to make it easier to refer to your words and ridicule you in public.<br />
<br />
== Other Suggestions ==<br />
This article is about elegance, so could we please inject some elegance into the article itself? Why do many of the functions have no type declaration? It took me quite some time to figure out the type declaration on foreach2: Monad m => [a] -> [b] -> (a -> b -> m c) -> m ()<br />
<br />
These functions should actually be tested. The way linify is currently defined, it produces 4 GHC warnings. I do not even know how to get rid of 2 of them.<br />
<br />
Readability could be considerably improved. At the moment, many sections start out fine, but then they suffer from a long list of additions which have not been properly integrated, so it reads something like this: Do this. Oh, but there is this too, and there is this caveat, but you could also do this, and performance is sometimes better if you do this, ...<br />
<br />
May I also suggest that periods be left off the end of a sentence whose last word is a code section? Currently, the article is formatted such that I have this: Words words words, see my code here:<br /><br />
\n<br /><br />
[ Code section<br /><br />
Code section<br /><br />
Code section]<br /><br />
\n<br /><br />
.<br /><br />
\n<br />
<br />
That is ridiculous. Just remove the period and the entailing massive whitespace.<br />
<br />
== Flame Away ==<br />
<br />
=== Avoid recursion ===<br />
<br />
Many times explicit recursion is the fastest way to implement a loop.<br />
e.g.<br />
<haskell><br />
loop 0 _ acc = acc<br />
loop i v acc = ...<br />
</haskell><br />
<br />
Using HOFs is more elegant, but makes it harder to reason about space usage,<br />
also explicit recursion does not make the code hard to read - just explicit<br />
about what it is doing.<br />
<br />
-- EinarKarttunen<br />
<br />
I disagree with this. Sometimes explicit recursion is simpler to design, but I don't see how it makes space usage any easier to reason about and can see how it makes it harder. By using combinators you only have to know the properties of the combinator to know how it behaves, whereas I have to reanalyze each explicitly implemented function. StackOverflow gives a good example of this for stack usage and folds. As far as being "faster" I have no idea what the basis for that is; most likely GHC would inline into the recursive version anyways, and using higher-order list combinators makes deforesting easier. At any rate, if using combinators makes it easier to correctly implement the function, then that should be the overriding concern.<br />
<br />
-- DerekElkins<br />
<br />
----<br />
I read lots of code with recursion -- and it was hard to read, because it is hard to retrieve the data flow from it. -- HenningThielemann<br />
<br />
----<br />
IMO explicit recursion usually ''does'' make code harder to read, as it's trying to do two things at once: Recursing and performing the actual work it's supposed to do. Phrases like OnceAndOnlyOnce and SeparationOfConcerns come to the mind.<br />
However, the concern about efficiency is (partly) justified. HOFs defined for certain recursion patterns often need additional care to achieve the same performance as functions using explicit recursion. As an example, in the following code, two sum functions are defined using two equivalent left folds, but only one of the folds is exported. Due to various peculiarities of GHCs strictness analyzer, simplifier etc, the call from main to mysum_2 works, yet the call to mysum_1 fails with a stack-overflow.<br />
<haskell><br />
module Foo (myfoldl_1, mysum_1, mysum_2) where<br />
<br />
-- exported<br />
myfoldl_1 f z xs = fold z xs<br />
where<br />
fold z [] = z<br />
fold z (x:xs) = fold (f z x) xs<br />
<br />
-- not exported<br />
myfoldl_2 f z xs = fold z xs<br />
where<br />
fold z [] = z<br />
fold z (x:xs) = fold (f z x) xs<br />
<br />
mysum_1 = myfoldl_1 (+) 0<br />
mysum_2 = myfoldl_2 (+) 0<br />
</haskell><br />
<haskell><br />
module Main where<br />
<br />
import Foo<br />
<br />
xs = [1..1000*1000]<br />
<br />
main = do<br />
print (mysum_2 xs)<br />
print (mysum_1 xs)<br />
</haskell><br />
(Results might differ for your particular GHC version, of course...)<br />
-- RemiTurk<br />
<br />
GHC made "broken" code work. As covered in StackOverflow, foldl is simply not tail-recursive in a non-strict language. Writing out mysum would still be broken. The problem here isn't the use of a HOF, but simply the use of non-tail-recursive function. The only "care" needed here is not relying on compiler optimizations (the code doesn't work in my version of GHC) or the care needed when relying on compiler optimizations. Heck, the potential failure of inlining (and subsequent optimizations following from it) could be handled by restating recursion combinator definitions in each module that uses them; this would still be better than explicit recursion which essentially restates the definition for each expression that uses it.<br />
<br />
-- DerekElkins<br />
<br />
Here is a demonstration of the problem - with the classic sum as the problem.<br />
Of course microbenchmarking has little sense, but it tells<br />
us a little bit which combinator should be used.<br />
<br />
<haskell><br />
import Data.List<br />
import System<br />
<br />
sum' :: Int -> Int -> Int<br />
<br />
sum' 0 n = sum [1..n]<br />
sum' 1 n = foldl (\a e -> a+e) 0 [1..n]<br />
sum' 2 n = foldl (\a e -> let v = a+e in v `seq` v) 0 [1..n]<br />
sum' 3 n = foldr (\a e -> a+e) 0 [1..n]<br />
sum' 4 n = foldr (\a e -> let v = a+e in v `seq` v) 0 [1..n]<br />
sum' 5 n = foldl' (\a e -> a+e) 0 [1..n]<br />
sum' 6 n = foldl' (\a e -> let v = a+e in v `seq` v) 0 [1..n]<br />
sum' 7 n = loop n 0<br />
where loop 0 acc = acc<br />
loop n acc = loop (n-1) (n+acc)<br />
sum' 8 n = loop n 0<br />
where loop 0 acc = acc<br />
loop n acc = loop (n-1) $! n+acc<br />
<br />
<br />
main = do [v,n] <- getArgs<br />
print $ sum' (read v) (read n)<br />
</haskell><br />
<br />
When executing with n = 1000000 it produces the following results:<br />
* seq does not affect performance - as excepted.<br />
* foldr overflows stack - as excepted.<br />
* explicit loop takes 0.006s<br />
* foldl takes 0.040s<br />
* foldl' takes 0.080s<br />
<br />
In this case the "correct" choice would be foldl' - ten times slower than explicit recursion.<br />
This is not to say that using a fold would not be better for most code. Just that it can<br />
have subtle evil effects in inner loops.<br />
<br />
-- EinarKarttunen<br />
<br />
This is ridiculous. The "explicit recursion" version is not the explicit recursion version of the foldl' version. Here is another set of programs and the results I get:<br />
<haskell><br />
import Data.List<br />
import System<br />
<br />
paraNat :: (Int -> a -> a) -> a -> Int -> a<br />
paraNat s = fold<br />
where fold z 0 = z<br />
fold z n = (fold $! s n z) (n-1)<br />
<br />
localFoldl' c = fold<br />
where fold n [] = n<br />
fold n (x:xs) = (fold $! c n x) xs<br />
<br />
sumFoldl' :: Int -> Int<br />
sumFoldl' n = foldl' (+) 0 [1..n]<br />
<br />
sumLocalFoldl' :: Int -> Int<br />
sumLocalFoldl' n = localFoldl' (+) 0 [1..n]<br />
<br />
sumParaNat :: Int -> Int<br />
sumParaNat n = paraNat (+) 0 n<br />
<br />
sumRecursionNat :: Int -> Int<br />
sumRecursionNat n = loop n 0<br />
where loop 0 acc = acc<br />
loop n acc = loop (n-1) $! n+acc<br />
<br />
sumRecursionList :: Int -> Int<br />
sumRecursionList n = loop [1..n] 0<br />
where loop [] acc = acc<br />
loop (n:ns) acc = loop ns $! n+acc<br />
<br />
main = do<br />
[v,n] <- getArgs<br />
case v of<br />
"1" -> print (sumFoldl' (read n))<br />
"2" -> print (sumLocalFoldl' (read n))<br />
"3" -> print (sumParaNat (read n))<br />
"4" -> print (sumRecursionNat (read n))<br />
"5" -> print (sumRecursionList (read n))<br />
</haskell><br />
<br />
(best but typical real times according to time of a few trials each)<br />
<haskell><br />
sumFoldl' takes 2.872s<br />
sumLocalFoldl' takes 1.683s<br />
sumParaNat takes 0.212s<br />
sumRecursionNat takes 0.213s<br />
sumRecursionList takes 1.669s<br />
</haskell><br />
<br />
sumLocalFoldl' and sumRecursionList were practically identical in performance and sumParaNat and sumRecursionNat were practically identical in performance. All that's demonstrated is the cost of detouring through lists (and the cost of module boundaries I guess).<br />
<br />
-- DerekElkins<br />
<br />
=== n+k patterns ===<br />
<br />
n+k patterns are similar to the definition of infix functions,<br />
thus they make it harder to understand patterns.<br />
http://www.dcs.gla.ac.uk/mail-www/haskell/msg01131.html (Why I hate n+k)<br />
<br />
So far I have seen only one rule for Good Coding Practice in Haskell: Do Not<br />
Use n+k Patterns. I hope someone can give some directions, how to avoid known<br />
pitfalls (especially Space Leaks).<br />
-- On the haskell mailing list<br />
<br />
The most natural definition of many functions on the natural numbers is by induction, a fact that can very nicely be expressed with the (n+1)-pattern notation. Also, (n+k)-patterns are unlikely to produce space leaks, since if anything, they make the function stricter. The possible ambiguities don't seem to appear in real code.<br />
--ThomasJäger<br />
<br />
If natural numbers would be defined by PeanoNumbers then pattern matching on successors would be straightforward. This would be fairly slow and space consuming, that's why natural numbers are not implemented this way. They are implemented using binary numbers and it is not even tried to simulate the behaviour of <hask>Natural</hask> (e.g. laziness). Thus I wouldn't state, that <hask>3</hask> matches the pattern <hask>2+1</hask>. -- HenningThielemann<br />
<br />
Lazyness/Strictness isn't really an argument in this situation, since when using a strict natural type, e.g.<br />
<haskell><br />
data Nat = Zero | Succ !Nat<br />
</haskell><br />
pattern matching on Nat behaves exactly like n+1 patterns. -- ThomasJaeger<br />
<br />
n+k patterns also apply to negative numbers - don't they?<br />
Yes, I see the analogy but in the current implementation it's nothing than sugar.<br />
-- HenningThielemann<br />
<br />
No, they don't. `let f (n+2) = n in f 1` is a runtime error. -- DerekElkins<br />
<br />
But translating it into pattern matching is impossible, thus it must be a static error. -- HenningThielemann<br />
<br />
=== Use syntactic sugar wisely ===<br />
I have to say, i strongly disagree with most of what is said in this section. First of all the claim<br />
<br />
''Syntactic extensions make source code processors complicated and error prone. But they don't help to make programs safer (like type checks and contracts) or easier to maintain (like modularization and scoping).''<br />
<br />
is obviously wrong. There certainly are applications of syntatic sugar that make programs easier to read, therefore easier to understand, easier to maintain, and safer, as you are more likely to spot bugs.<br />
<br />
:My statement was: Don't use syntactic sugar by default because you believe it makes your program more readable automatically (I've read lots of code of programmers who seem to believe that), but use syntactic sugar '''if''' (and only if) it makes the program '''more''' readable. Syntactic sugar is only a matter of readability not of safety in the sense of scoping and type checking. If I accidentally introduce inconsistencies into my code, the name resolver or the type checker will report problems, but not the de-sugarizer. -- HenningThielemann<br />
<br />
ad. right sections are evil<br />
<br />
I can't believe someone is seriously advocating to replace <hask>(&$ x)</hask> with the less readable <hask>flip (&$) x</hask> just because that's the way one specific haskell implementation is reporting errors. Most of the time, I don't even care to read type errors because once I know which line the error occured in, it is usually immediately clear what the error was. Even if you have to read the error message, there should be no difficulty to see that (+1) and flip (+) 1 is the same thing, especially when used in a context.<br />
<br />
:Nobody advocated for replacing <hask>($ x)</hask> by <hask>flip ($) x</hask> this was just to demonstrate the problems arising with syntactic sugar. I believe that many people don't take that into account when requesting more sugar (such as parallel list comprehension). -- HenningThielemann<br />
<br />
''Infix notation is problematic for both human readers and source code formatters.''<br />
<br />
No, infix notation isn't problematic for human readers, it enables them to read the code faster in many cases.<br />
<br />
:... if he knows the precedences, which is only true for (some) of the predefined operators. I guess you don't know all of the precedences of the Prelude operators. I also use infix operations like (+) and (:) but I'm very concerned with introducing lots of new operator symbols and `f` notation. -- HenningThielemann<br />
<br />
:Introducing new operators should definitely not be done careless (then again, one shouldn't be careless in programming anyway), and operator percedences might be better defined as a partial order. (e.g. there is an order between (+) and (*), and between (&&) and (||), but not between (+) and (&&)). Other proposals for replacing the current left/right associative + precedence system do exist. However, doing away with infix operators entirely appears to me to practically render combinator libraries unusable, which would make Haskell a lot less attractive. -- RemiTurk<br />
<br />
:The nice thing about precedences in Haskell is that it's often not necessary to know them exactly in order<br />
to use them. If the types of you operators are sufficiently general, or sufficiently distinct, only the sight way to parse them will lead to type-checking code, so you can just give it a shot without parenthesis and hopefully remember the precedence the next time you're in a similar situation. -- ThomasJaeger<br />
<br />
<hask>(+1) `fmap` m</hask> expresses that the <hask>fmap</hask> is just a fancy function application, when writing interpreter-like code <hask>Var "f" `App` Var "x" `App` "y"</hask> is certainly more readable and can be written much faster than <hask>App (App (Var "f") (Var "x")) (Var "y"))</hask> and our brains have been trained to parse + and * with different precendences since elementary school.<br />
<br />
:If you make it for readability, I agree, if you make it for fancyness, I disagree. In the case of <hask>App</hask> it looks like the list can become longer, so it's worth of thinking about using <hask>foldl</hask>, <hask>App</hask> and a list - though then I would certainly also use some syntactic sugar to enter the list <hask>["f", "x", "y"]</hask>. Btw. even the regular list notation is disputable since in the infix notation <hask>("f":"x":"y":[])</hask> it is easier move elements around. So I end up with infix notation, ok. Even more, <hask>foldl</hask> shows clearly the left associativity, whereas <hask>`App`</hask> does not.<br />
:In the case of <hask>`on`</hask> and <hask>compose2</hask>, I disagree. <hask>on</hask> is less informative than <hask>compose2</hask>. And yes, <hask>compose2</hask> is a kind of generalization of <hask>.</hask>, though it is not the most popular one. -- HenningThielemann<br />
<br />
:You do indeed have a point there: it's indeed ''an'' extension of <hask>(.)</hask>, which I incorrectly denied. However, as it's not ''the'' extension, and AFAIK not even ''the most used'' extension, I consider the name <hask>compose2</hask> to be slightly misleading. In addition, I think "group by equality on isAlpha" (<hask>groupBy ((==) `on` isAlpha)</hask>) is just too cute too resist. -- RemiTurk<br />
<br />
::So, do you do it for readability or for fanciness? I find an infix function application hard to read, since it looks like just another argument. That is, <hask>((==) `on` isAlpha)</hask> reads very similar to <hask>((==) on isAlpha)</hask>. In your example you really switch the prefered usage of the identifiers, you use the infix symbol <hask>==</hask> in prefix notation and the prefix function name <hask>on</hask> in infix notation. -- HenningThielemann<br />
<br />
::Any kind of syntax highlighting should make the difference between <hask>((==) `on` isAlpha)</hask> and <hask>((==) on isAlpha)</hask> obvious. Another argument for using an infix <hask>on</hask> here is that it explains the order of the elements: Deciding if <hask>on (==) isAlpha</hask> or <hask>on isAlpha (==)</hask> is better and trying to remember which way the implementor choose is certainly more difficult than realizing that <hask>isAlpha `on` (==)</hask> makes no sense (There are better examples for this such as <hask>`elem`</hask>, or think about the confusion between the order of arguments in <hask>Data.FiniteMap</hask> vs. <hask>Data.Map</hask>). -- ThomasJaeger<br />
<br />
:::Btw. the function <hask>comparing</hask> has found its way to the module <hask>Data.Ord</hask> (http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-Ord.html). It is a composition of <hask>compare</hask> and <hask>on</hask>/<hask>compose2</hask>. However it does not satisfyingly help to implement extensions of <hask>*By</hask> functions, because the key for sorting/grouping/maximising must be re-computed for each comparison if you write, say <hask>sortBy (comparing length)</hask>. -- HenningThielemann<br />
<br />
:Of course, <hask>foldl App</hask> only works if <hask>App</hask> models application in an untyped language. Using GADTs, <hask>App</hask> could be of type <hask>Expr (a -> b) -> Expr a -> Expr b</hask>, also, many combinator that works on different types can't be "sugared" using functions. -- ThomasJaeger<br />
<br />
<br />
Finally, there is no reason why one should expect a tool that processes haskell code not to be aware of Haskell 98's syntax. All mentioned syntactic extensions (list comprehension, guards, sections, infix stuff) fall under this category and can be used without any bad conscience.<br />
<br />
Sorry for having become so "religous" -- ThomasJaeger<br />
<br />
<br />
I agree. -- CaleGibbard<br />
<br />
<br />
:If you want a good example for unnecessary sugar, take this one:<br />
<haskell><br />
tuples :: Int -> [a] -> [[a]]<br />
tuples 0 _ = return []<br />
tuples (r+1) xs = do<br />
y:ys <- tails xs<br />
(y:) `fmap` tuples r ys<br />
</haskell><br />
:Why is infix <hask>`fmap`</hask> more readable than prefix <hask>fmap</hask>? Where is the analogy to <hask>map</hask>? Why don't you use <hask>map</hask> at all? I see <hask>map</hask> as an operator which lifts scalar functions to list functions, this is perfectly expressed by prefix notation. What is the readability benefit of <hask>(r+1)</hask> pattern and why is <hask>do</hask> more readable than explicit <hask>init (tails xs) >>= (\(y:ys) -> map (y:) (tuples (r-1) ys))</hask> here? ('''Mostly because this is not the correct translation and the correct translation ''is'' unreadable -- DerekElkins''') It's even worse than <hask>[(y:) `fmap` tuples r ys | (y:ys) <- tails xs]</hask>. You rewrote my code just with sugar but the structure which must be understood remained the same. Sorry, I don't find it easier to understand. Maybe people who believe a common notation rather than to try to understand the meaning are happy with the sugar. -- HenningThielemann<br />
<br />
:''The pattern <hask>m >>= \x -> f x</hask> is exactly the reason the do-notation was introduced, so each time I write something like this, I replace it with a do notation for the following reason: It is definitely the more common style (nobody is using <hask>m >>= \x -> \n</hask>-style these days), so much more likely to be understood faster (at least for myself), the do notation expresses nicely that monadic (in this case notdeterminstic) effects are taking place, and finally it is much easier to make changes to the code if it's in do-form (e.g. add additional guards). Of course you CAN do the same changes in <hask>>>=</hask>-style, too, after all there is a straightforward translation (although complicated by the fact that you have to check if pattern matchings are exhaustive), but I'm not the kind of guy who does all kinds of verbose translation in his head just because he wants to stay away from syntactic sugar.<br />
<br />
::I disagree with arguments like "nobody is using ...". What does it tell about the quality of a technique? I write here to give reasons against too much syntactic sugar rather than to record today's habits of some programmers. -- HenningThielemann<br />
<br />
:You are further critizing that I am using <hask>fmap</hask> instead of the more special <hask>map</hask>. I find it natural to use <hask>fmap</hask> in monadic code to abstract from lists. If it weren't for <hask>tails</hask>, the code would even have type <hask>(MonadPlus m, Functor m) => Int -> [a] -> m [a]</hask>, increasing usability. <hask>liftM</hask> would also be acceptable (and for some strange reason even slightly faster), but it feels awfully wrong to me to use <hask>liftM</hask>, so that I'm willing to live with additional <hask>Functor</hask> constraints. This is also the reason while your list comprehension solution is clearly inferior to a monadic one.<br />
<br />
:One more thing about pattern match failure vs. <hask>init</hask>. Though it doesn't matter match in this simple example, the version exploiting pattern match failure is closer to the conceptional algorithm, because it doesn't rely on the "low-level-property" of <hask>tails</hask> that the empty list is the last element of the returned list (I can never remember this kind of things, even though one of the possible behaviors makes much more sense).<br />
<br />
:The function <hask>tuples</hask> is defined by recursion on an Int and only uses the case of the predecessor, so this is a classical example for (n+1)-patterns. Note that the LHSs in your implementation are overlapped, so a reader might need more time to figure out what is going on in your implementation (I admit the effect is small, but this is a very tiny example).<br />
<br />
:Using <hask>fmap</hask> infix is a personal habit of mine, but when you think about it, it makes a lot of sense. As we can't overload a space, it's the closest thing to application syntax we can get. I know you prefer <hask>App (App f x) y</hask>-style, which seems more difficult to understand for most people. This just is a matter of personal style. Please do not mistake your own personal style for the only sensible one.<br />
<br />
:If no one else objects, I'd like to put my implementation back on the main page, possibly with a less controversial comment. --ThomasJaeger''<br />
<br />
::My argument is that the syntactic sugared version may be readable ''like'' the unsugared version, but it does not ''improve'' the readability, thus it should be avoided. Sugar shouldn't be the default, it shouldn't used just because it exists. That's the basic opinion where we disagree. Btw. I find the <hask>do</hask> notation in connection with the <hask>List</hask> monad very confusing because it looks imperative and it suggests that first something is chosen from the list then it is returned. -- HenningThielemann<br />
<br />
::While it may not be more readable for you, it is for me, for the reasons I'm getting tired of stating. Also, your opinions on the do-notation seem very strange to me. If we have monads - a way to unify different notions of effects - why make the artificial distinction between IO/State effects and more general ones again? The do-notation expresses in which order the effects are happening - that's the same for a list and an IO monad. However, a distinction between commutative and non-commutative monads would make sense, but unfortunately, there's no way to prove the commutativity of a monad statically in Haskell.<br />
<br />
There are still issues that aren't implemented in GHC which belong to the Haskell 98 standard and which are of more importance, I think, such as mutual recursive modules and some special case of polymorphic mutual function recursion. So I don't vote for wasting the time with syntactic sugar when real enhancements are deferred by it. If I would write a Haskell code processor I would certainly prevent me from the trouble of supporting guards and (n+k) patterns. I'm also fed up with the similar situation in HTML with its tons of extensions and the buggy code which is accepted by most browsers (which is also a sort of inofficial extension) - there is simply no fun in processing HTML code. Not to mention C++.<br />
<br />
By the way I'd like to have a real function <hask>if</hask> instead of the sugarized version with <hask>then</hask> and <hask>else</hask> in Haskell 98. Then I could use it in connection with <hask>zipWith3</hask>. See ["Case"] for another application. -- HenningThielemann<br />
<br />
: Agrees with that. I'm not using <hask>if</hask> all that often, and could easily add a few braces. And, it would free <hask>then</hask> and <hask>else</hask> for normal identifier use. -- RemiTurk<br />
<br />
Personally, I like the explicit `then` and `else` and find that they help when reading code to separate where the break is between the sections. It's not that I necessarily disagree with the inclusion of such a function, it is an easy one to write in any case, but I think that some sugar in the form of a few extra words to mark important points in common structures is useful. Human languages have many such words, and their presence makes reading or listening much easier. - CaleGibbard<br />
<br />
: Other people seem to have problems with this special syntax, too. And they propose even more special syntax to solve the problem. https://gitlab.haskell.org/haskell/prime/-/wikis/do-and-if-then-else -- HenningThielemann</div>Takenobu.hshttps://wiki.haskell.org/index.php?title=Haskell%E5%85%A5%E9%96%80_5%E3%82%B9%E3%83%86%E3%83%83%E3%83%97&diff=63131Haskell入門 5ステップ2019-11-16T07:44:46Z<p>Takenobu.hs: Add communities of haskell.org and haskell.jp</p>
<hr />
<div>Haskellは汎用の純粋関数型プログラミング言語です。このページではなるべく早くHaskellが使えるようになるよう手助けとなる解説をします。<br />
<br />
__TOC__<br />
<br />
== Haskellのインストール ==<br />
<br />
他の多くのプログラミング言語と同様に、Haskellは2種類の方法で使うことができます。<br />
一つバイナリ(コンパイラ)でもう一つはインタラクティブシェル(インタプリタ)です。<br />
インタラクティブシェルでは式を試したり評価したりすることができます。<br />
まずはインタラクティブシェルで始めるのがよいでしょう。<br />
<br />
{| class="wikitable"<br />
|[http://www.haskell.org/ghc/ GHC]<br />
|コンパイラとインタプリタ (GHCi)<br />
|おそらく最も多くの機能が実装されたシステム<br />
|-<br />
|[http://www.haskell.org/hugs/ Hugs]<br />
|インタプリタのみ<br />
|GHCより軽量でとてもお手軽<br />
|}<br />
<br />
WindowsではGHCとHugsの両方が動作しますが、HugsのほうがよりWindowsとの親和性が高いと思われます。しかし、GHCが最も活発に開発やメンテナンスが行われているので、たいていの人は入門者はもちろん、プログラミングになれた人にもGHCを勧めます。またここにも[[Mac OS X|Mac OS XにHaskellをインストールする]]方法が載っています。<br />
<br />
== Haskell事始め ==<br />
<br />
ターミナルを開いてください。もしGHCをインストール済みであれば、コマンドプロンプトに"ghci"と入力してください。(GHCインタプリタの実行ファイル名です)Hugsをインストール済みであれば"hugs"と入力してください。<br />
<br />
<pre><br />
$ ghci<br />
___ ___ _<br />
/ _ \ /\ /\/ __(_)<br />
/ /_\// /_/ / / | | GHC Interactive, version 6.4, for Haskell 98.<br />
/ /_\\/ __ / /___| | http://www.haskell.org/ghc/<br />
\____/\/ /_/\____/|_| Type :? for help.<br />
<br />
Loading package base-1.0 ... linking ... done.<br />
Prelude><br />
</pre><br />
<br />
そしてプロンプトが表示されます。これでHaskellが起動し入力待ちの状態となりました。<br />
<br />
== 初めてのHaskellプログラムを書いてみよう ==<br />
<br />
他のプログラミング言語を学ぶ場合、まず最初に "Hello, world!" を書いたことと思います。なのでまずはそれをやってみましょう。<br />
<br />
<haskell><br />
Prelude> "Hello, World!"<br />
"Hello, World!"<br />
</haskell><br />
<br />
Haskellは文字列を評価して、結果を表示しました。<br />
今度は別の方法で標準出力に直接表示させてみましょう。<br />
<br />
<haskell><br />
Prelude> putStrLn "Hello World"<br />
Hello World<br />
</haskell><br />
<br />
[http://haskell.org/ghc GHC]のようなHaskellコンパイラを使って、コードをコンパイルしてスタンドアロンで動作する実行ファイルを作ることもできます。 次のようなコードを書いて、'''hello.hs''' として保存します。<br />
<br />
<haskell><br />
main = putStrLn "Hello, World!"<br />
</haskell><br />
<br />
そして次のようにしてコンパイルします。<br />
<br />
<pre><br />
$ ghc -o hello hello.hs<br />
</pre><br />
<br />
そして実行ファイルを走らせてみてください。(Unixでは'''./hello'''、Windowsでは'''hello.exe'''を実行してください)<br />
<br />
<pre><br />
$ ./hello<br />
Hello, World!<br />
</pre><br />
<br />
== 電卓としてのHaskell ==<br />
<br />
楽しいことをしてみましょう。Haskellでの真に最初のプログラムは階数を計算する関数です。再びインタプリタに戻って関数を定義してみましょう。<br />
<br />
<haskell><br />
Prelude> let fac n = if n == 0 then 1 else n * fac (n-1)<br />
</haskell><br />
<br />
これで整数の階数を計算する新しい関数 '''fac''' を定義しています。<br />
<br />
'''fac''' にいくつか引数を与えて実行することができます。<br />
<haskell><br />
Prelude> fac 42<br />
1405006117752879898543142606244511569936384000000000<br />
</haskell><br />
<br />
'''おめでとうございます!''' プログラミングによって一つ便利になりました。Hugsを使っている場合は、以下のようなコードを保存したファイル '''fac.hs''' から '''fac''' の定義を読み込む必要があるので気をつけてください。<br />
<br />
<haskell><br />
fac n = if n == 0 then 1 else n * fac (n-1)<br />
</haskell><br />
<br />
そしてHugsでは次のように実行します。(GHCでも同様にして動きます)<br />
<br />
<haskell><br />
Hugs.Base> :load fac.hs<br />
Main> fac 42<br />
1405006117752879898543142606244511569936384000000000<br />
</haskell><br />
<br />
もちろんこのプログラムをコンパイルしてスタンドアロンな実行ファイルを生成することもできます。'''fac.hs''' を次のように書いてみましょう。(今度はちょっとおもしろそうなので美しいパターンマッチの構文を使ってみましょう)<br />
<br />
<haskell><br />
fac 0 = 1<br />
fac n = n * fac (n-1)<br />
<br />
main = print (fac 42)<br />
</haskell><br />
<br />
そしてコンパイルして実行します。<br />
<br />
<pre><br />
$ ghc -o fac fac.hs<br />
$ ./fac<br />
1405006117752879898543142606244511569936384000000000<br />
</pre><br />
<br />
'''すごい!'''<br />
<br />
===初めてのHaskell並列プログラミング===<br />
<br />
Haskellでは並列化/マルチコアプログラミングをサポートしています。式に `par` と付け加えることで、このように並列プログラムを書くことができます。<br />
<br />
<haskell><br />
import Control.Parallel<br />
<br />
main = a `par` b `par` c `pseq` print (a + b + c)<br />
where<br />
a = ack 3 10<br />
b = fac 42<br />
c = fib 34<br />
<br />
fac 0 = 1<br />
fac n = n * fac (n-1)<br />
<br />
ack 0 n = n+1<br />
ack m 0 = ack (m-1) 1<br />
ack m n = ack (m-1) (ack m (n-1))<br />
<br />
fib 0 = 0<br />
fib 1 = 1<br />
fib n = fib (n-1) + fib (n-2)<br />
</haskell><br />
<br />
コンパイル時に -threaded と最適化オプションをつけます。<br />
<br />
<pre><br />
$ ghc -O2 --make A.hs -threaded<br />
[1 of 1] Compiling Main ( A.hs, A.o )<br />
Linking A ...<br />
</pre><br />
<br />
これでマルチコアプログラムを動かすことができます。2コアの場合の例です。<br />
<br />
<pre><br />
$ time ./A +RTS -N2<br />
1405006117752879898543142606244511569936384005711076<br />
./A +RTS -N2 2.14s user 0.02s system 149% cpu 1.449 total<br />
</pre><br />
<br />
おめでとうございます!これでマルチコアでのプログラミングもできてしまいましたね!<br />
<br />
== 次にすることは? ==<br />
<br />
たくさんのHaskellのチュートリアルや書籍があります。ここにいくつかおすすめを書いておきます。<br />
<br />
'''チュートリアル'''<br />
* [[10分で学ぶHaskell]]<br />
* [http://darcs.haskell.org/yaht/yaht.pdf Yet Another Haskell Tutorial] (English)<br />
* [http://www.haskell.org/tutorial/ A Gentle Introduction to Haskell] (English, [[Image:GentleFR.pdf|French PDF]])<br />
* [http://learnyouahaskell.com/ Learn You A Haskell For Great Good!]<br />
<br />
書籍やチュートリアルのリストはここです:<br />
<br />
* [[Books and tutorials]]<br />
<br />
'''コミュニティに参加しましょう!'''<br />
<br />
いろんな人にHaskellコミュニティを紹介してください:<br />
<br />
* [http://haskell.org/mailman/listinfo/haskell-cafe Haskell-Cafe mailing list] <br />
* [[IRC channel]]<br />
* [https://www.haskell.org/community/ www.haskell.org/community] <br />
* [https://haskell.jp/ Haskell-jp] (Japanese)<br />
<br />
[[Category:Tutorials]]<br />
Languages: [[Haskell in 5 steps|en]]</div>Takenobu.hshttps://wiki.haskell.org/index.php?title=User_groups&diff=61806User groups2017-05-13T12:52:39Z<p>Takenobu.hs: Add Haskell-jp</p>
<hr />
<div>[[Category:Community]]<br />
<br />
A range of Haskell User Groups are springing up all over.<br />
<br />
== Online communities ==<br />
* [http://www.reddit.com/r/haskell/ Haskell Reddit]<br />
* [http://stackoverflow.com/questions/tagged?tagnames=haskell Haskell on Stack Overflow]<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 />
<br />
===Africa===<br />
<br />
====South Africa====<br />
; [http://www.meetup.com/lambda-luminaries/ Lambda Luminaries] : Functional programming user group based in Centurion, Gauteng.<br />
<br />
===Asia===<br />
<br />
====China====<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 />
====Hong Kong====<br />
;[http://www.meetup.com/HK-Functional-programming/ Hong Kong Functional Programming User Meetup Group]<br />
<br />
====Japan====<br />
;[https://haskell.jp/ Japan Haskell Users Group (Haskell-jp)]<br />
:blog, slack, recipes, events (meetings) and more<br />
<br />
;[http://www.starling-software.com/en/tsac.html Tokyo Society for the Application of Currying]<br />
<br />
;[http://www.meetup.com/Tokyo-Haskell-Meetup/ Tokyo Haskell Meetup]<br />
:Casual monthly meetings to help each other learn Haskell<br />
<br />
===Europe===<br />
<br />
==== Belgium ====<br />
<br />
;[[Ghent Functional Programming Group]]<br />
:The Ghent Functional Programming Group will be having its first meeting on April 1, 2010.<br />
<br />
;[https://groups.google.com/forum/#!forum/leuven-haskell Leuven Haskell User Group]<br />
:The Leuven Haskell User Group was launched on March 3, 2015 and meets every two weeks.<br />
<br />
==== France ====<br />
<br />
;[[Fr/Haskell]]<br />
:The Strasbourg HUG meets monthly in an informal setting. Level is very low and newbies are very welcome.<br />
<br />
==== Germany ====<br />
<br />
;Curry Club Augsburg<br />
:http://curry-club-augsburg.de/<br />
<br />
;Berlin HUG<br />
:http://www.meetup.com/berlinhug/<br />
<br />
;Haskell in Frankfurt<br />
: <ul><li>[http://www.meetup.com/Frankfurt-Haskell-User-Group Frankfurt Haskell User Group] meets monthly.</li><li> [http://wiki.lug-frankfurt.de/Programmierworkshop/aktuell Regular Saturday Workshop] taking place every couple of months. Feel free to join us!</li><br />
<br />
;[http://www.iba-cg.de/hal5.html Haskell in Leipzig]<br />
:Hal, they have videos [http://iba-cg.de/haskell.html online].<br />
<br />
;[http://www.haskell-munich.de Haskell in Munich]<br />
: We had our first meeting on Thursday, 29th of September 2011. We are always looking forward to see new people. If you can make it to Munich, consider joing us!<br />
<br />
;[http://www.meetup.com/de-DE/Regensburg-Haskell-Meetup Regensburg Haskell Meetup]<br />
: We meet regularly once a month since 2014. Folks from the Munich and Nuremberg area frequently join.<br />
<br />
;Interest for User Groups in Germany<br />
* '''Ulm''': [[HugUlm]]<br />
* '''Mannheim or Heidelberg''': [[User:Cgo|cgo]] ([http://www.haskell.org/haskellwiki/?title=Special:Emailuser&target=Cgo mail]), [[User:HC|hc]]<br />
<br />
==== Greece ====<br />
<br />
;[https://groups.google.com/forum/#!forum/haskell-greece/ Haskell Greece Google group]<br />
<br />
==== Hungary ====<br />
<br />
;[http://www.meetup.com/Bp-HUG Budapest Haskell User Group]<br />
:The Haskell User Group is a group of Haskell enthusiasts who are interested in sharing their knowledge and meeting people who share similar interests. We had our first meeting in September 2013.<br />
<br />
==== Iceland ====<br />
<br />
;[[Reykjavik Haskell User Group]] Iceland<br />
;[http://groups.google.com/group/haskell-is Currently recruiting members]<br />
<br />
==== Israel ====<br />
<br />
;[[IsraelHaskell]] User Group<br />
:[http://article.gmane.org/gmane.comp.lang.haskell.cafe/28877 Are getting organised].<br />
* '''Konstanz''': [[User:Thkoch|thkoch]]<br />
<br />
==== Italy ====<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 />
==== Netherlands ====<br />
<br />
;[http://dutchhug.nl/ Dutch HUG]<br />
:The Dutch HUG meets monthly in an informal setting.<br />
<br />
==== Norway ====<br />
<br />
;[http://www.meetup.com/Oslo-Haskell/ Osλo Haskell]<br />
:Osλo Haskell is a group for Haskellers and people interested in Haskell and related languages in and around Oslo. We had our first meeting in March 2014.<br />
<br />
;[http://www.meetup.com/Trondheim-Haskell-Users-Group/ Trondheim Haskell Users' Group]<br />
:A Haskell users' group in the Trondheim area. For seasoned veterans, complete newbies who only heard of Haskell two minutes ago, and everyone in between and beyond. We meet and talk about Haskell and anything else members are interested in.<br />
<br />
==== Poland ====<br />
;[https://plus.google.com/u/0/communities/103183708602453146804 HUG Warsaw] <br />
We are the successors to the Warsaw Functional Society (Warszawskie Towarzystwo Funkcyjne) and as such we welcome any functional programmers and enthusiasts, though the focus of the group is Haskell. We (hope to) have rather informal, but regular meetings in Warsaw, Poland.<br />
<br />
==== Russia ====<br />
<br />
;[http://ruhaskell.org/ Russian community of Haskell-developers]<br />
;[http://spbhug.folding-maps.org Saint-Petersburg Haskell User Group]<br />
;[https://groups.google.com/forum/#!forum/mskhug Moscow Haskell User Group]<br />
;[https://groups.google.com/forum/#!aboutgroup/haskell-russian haskell-russian mailing list]<br />
<br />
==== Switzerland ====<br />
<br />
;[http://www.meetup.com/HaskellerZ/ Haskell User Group Zurich]<br />
:We are meeting once a month to share knowledge of and experience with Haskell.<br />
<br />
;[http://www.meetup.com/Geneva-Haskell-Group/ Geneva Haskell Group]<br />
:We are a Haskell community in Geneva planning to meet up every week.<br />
<br />
==== Turkey ====<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 />
==== UK ====<br />
;[http://lambdalounge.org.uk/ Manchester Lambda Lounge]<br />
:We are an active community meeting monthly at the [http://madlab.org.uk/ Madlab] (Manchester Digital Laboratory) to talk about topics in functional programming.<br />
<br />
;[http://www.meetup.com/hoodlums/ Hoodlums - Haskell developer meetup]<br />
:Meets monthly on the second Thursday of the month in Canary Wharf. It is a "Coding Dojo" format where we pick some interesting problem and solve it as a group. <br />
<br />
;[http://www.meetup.com/London-HUG/ London Haskell User Group]<br />
:The main meetings are monthly on the last or fourth Thursday of the month. The group was revived in late 2012.<br />
<br />
;[http://www.meetup.com/ed-lambda/ ed lambda (Edinburgh, UK)]<br />
:For functional programming in general, founded by a Haskeller. First meeting will be September 13th 2010.<br />
<br />
;[http://groups.google.com/group/oxhug OxHUG - the Oxford Haskell Users Group]<br />
:Meets every other week, currently at the Department of Computer Science, University of Oxford. Discussion session followed by adjournment to a local tavern. Aimed at students, graduates, professionals and enthusiasts.<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 />
==== Ukraine ====<br />
;[https://groups.google.com/forum/#!forum/ltu-kiev LtU-Kiev community]<br />
:Irregular meetups, usually with prepared talks on Haskell and other FP topics.<br />
;[http://ro-che.info/odhug Odessa Haskell User Group]<br />
:Regular informal meetups (approximately once a month) in a pub or cafe<br />
<br />
===North America===<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://www.meetup.com/Boulder-Haskell-Programmers/ Boulder Haskell Programmers]<br />
: Boulder and Denver (Colorado) area Haskell Programmer Group. Meetings are focused on practical topics faced by working programmers. All experience levels are welcome.<br />
<br />
;[http://groups.google.com/group/real-world-haskell-book-club/browse_thread/thread/3e8e59768c8c50a9 Colorado Area Haskell Study Group]<br />
<br />
;[http://ChicagoHaskell.com Chicago Haskell] — First general meeting in December 2009. — [https://groups.google.com/forum/#!forum/haskell-chicago Mailing List] — [https://twitter.com/ChicagoHaskell @ChicagoHaskell]<br />
<br />
;[http://www.meetup.com/DenHUG/ Denver Area Haskell Users Group] -- DenHUG had it's first meeting on 27 Feb 2010. Next meeting will be 3 Apr 2010.<br />
<br />
;[http://www.meetup.com/Houston-Haskell-Users-Group/ Houston Haskell Users Group] -- Meets the 1st Monday of every month at [https://txrxlabs.org/ TxRx labs]<br />
<br />
;[http://www.lambdalounge.org St. Louis Lambda Lounge] -- Meets the 1st Thursday of the month. Since Dec 2008, Lambda Lounge is a user group in St. Louis organized loosely around the idea of exploring dynamic and functional languages.<br />
<br />
;[http://www.meetup.com/Nashville-Haskell-Users-Group Nashville Haskell Users Group (NHUG)] -- Meets 1st Tuesday of each month.<br />
<br />
====East Coast====<br />
<br />
;[http://groups.google.com/group/bostonhaskell Boston Haskell Users' Group].<br />
:Meets monthly.<br />
<br />
;[http://www.meetup.com/NY-Haskell/ New York Haskell Users Group]<br />
:The NY Haskell Users Group is for all programmers either interested in or experienced with the Haskell programming language. Meets monthly.<br />
<br />
;[http://www.meetup.com/lisp-59/ New York Functional Programmers]<br />
:Come and meet like-minded functional programmers in the New York area.<br />
<br />
;[http://www.meetup.com/Haskell-DC/ Haskell DC]<br />
:Washington DC area Meetup for Haskell.<br />
<br />
;[http://www.lisperati.com/fringedc.html FringeDC Washington]<br />
:Meetings about functional programming languages in Washington DC.<br />
<br />
;[http://groups.google.com/group/AFPUG Atlanta Functional Programming Users Group]<br />
:Meet other functional programmers in the Atlanta area. Join us and geek out!<br />
<br />
;Toronto Haskell User Group<br />
:Haskellers of Toronto, unite! We meet at [https://bentomiso.com/events Bento Miso] on the second Wednesday of every month (check the [https://bentomiso.com/events event page] to be sure; it's usually up-to-date). There is also a small organizational [http://groups.google.com/group/toronto-haskell/ mailing list] you can join to keep up to date.<br />
<br />
;[http://www.haskellers-montreal.com/ Haskellers Montreal Group].<br />
:Meets every 2 months on the first Wednesday of that month, currently at Centre [http://cloud.ca Cloud.ca] (previously known as RPM). Talks alternate from expert-level to more newcomer-oriented ones; and we organize through our [http://haskell-meetup.sandreckoning.com/ website], a [https://groups.google.com/forum/#!forum/haskellers-montreal Google group] and a [http://www.meetup.com/Haskellers-Montreal-Meetup/ meetup.com] page.<br />
<br />
====West Coast ====<br />
<br />
;[http://socalfp.blogspot.com/ SoCal FP Group]<br />
<br />
;[http://www.meetup.com/sandiegohug/ San Diego Haskell User Group]<br />
:a Haskell User Group for the San Diego and Tijuana region<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://seattlehaskell.org/ Seattle Area Haskell Users' Group]<br />
:Monthly get-togethers serving Seattle and the Eastside (see also [http://meetup.com/SEAHUG/ Meetup.com] for details)<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://www.meetup.com/Vancouver-Haskell-Unmeetup/ Vancouver Haskell UnMeetup]<br />
:Monthly interactive sessions, (+10) for joining<br />
<br />
===Oceania===<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://bfpg.org/ Brisbane Functional Programming Group (BFPG)] ([http://www.meetup.com/Brisbane-Functional-Programming-Group-BFG/ Meetup page])<br />
:A group for Functional Programming with Haskell, Scala and other languages.<br />
<br />
;[http://meetup.com/PerthFP/ Perth Functional Programmers Meetup]<br />
:A group in Perth, WA for Functional Programming with Haskell, Scala and other languages.<br />
<br />
===South America===<br />
<br />
==== Bolivia ====<br />
; [https://www.facebook.com/groups/111518795538430/ Comunidad Haskell San Simon (CHSS)]<br />
: Haskell user group for Bolivia and spanish speaking community<br />
<br />
====Brazil====<br />
;[[User_groups/Brazil|Grupo Brasileiro de Usuários de Haskell]]<br />
: Grupo criado para reunir os desenvolvedores e entusiastas que utilizam Haskell no Brasil<br />
<br />
====Ecuador====<br />
; [http://www.meetup.com/Quito-Lambda-Meetup/ Quito Lambda]<br />
: A monthly meetup about functional programming in Quito, Ecuador<br />
<br />
== Workshops/meet ups ==<br />
<br />
Less regular, and move around. Usually have a few talks from invited speakers.<br />
See the [[Haskell]] homepage for a list of upcoming events.<br />
<br />
== Hackathons ==<br />
<br />
Getting together to squash bugs and write new stuff. For a list of past and upcoming hackathons, see the [[Hackathon]] page.<br />
<br />
== Conferences ==<br />
<br />
See the [[Haskell_in_research#Conferences|Haskell in research]] and [[Conferences]] page for academic workshops and conferences<br />
focusing on Haskell and related technology.</div>Takenobu.hshttps://wiki.haskell.org/index.php?title=Kind&diff=61428Kind2017-01-14T03:52:32Z<p>Takenobu.hs: add references</p>
<hr />
<div>[http://en.wikipedia.org/wiki/Kind_%28type_theory%29 Wikipedia] says, "In type theory, a '''kind''' is the type of a type constructor or, less commonly, the type of a higher-order type operator. A kind system is essentially a simply typed lambda calculus 'one level up,' endowed with a primitive type, denoted * and called 'type', which is the kind of any (monomorphic) data type."<br />
<br />
Ordinary types have kind <TT>*</TT>. Type constructors have kind <TT>P -> Q</TT>, where <TT>P</TT> and <TT>Q</TT> are kinds. For instance:<br />
<br />
Int :: *<br />
Maybe :: * -> *<br />
Maybe Bool :: *<br />
a -> a :: *<br />
[] :: * -> *<br />
(->) :: * -> * -> *<br />
<br />
In Haskell 98, <TT>*</TT> is the only '''inhabited kind''', that is, all values have types of kind <TT>*</TT>. GHC introduces another inhabited kind, <TT>#</TT>, for [[unlifted type]]s.<br />
<br />
= See also =<br />
<br />
* [[GHC/Kinds]]<br />
* [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/Kinds Kinds] on the GHC Commentary<br />
* [https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/TypeType TypeType] on the GHC Commentary<br />
* [http://hackage.haskell.org/trac/ghc/wiki/IntermediateTypes#KindsareTypes Kinds ?, ??, # and (#)]<br />
* [[Books#Foundations|Pierce, Benjamin. ''Types and Programming Languages'']].<br />
<br />
[[Category:Language]]</div>Takenobu.hshttps://wiki.haskell.org/index.php?title=Kind&diff=60471Kind2015-12-31T15:41:14Z<p>Takenobu.hs: change unboxed to unlifted type</p>
<hr />
<div>[http://en.wikipedia.org/wiki/Kind_%28type_theory%29 Wikipedia] says, "In type theory, a '''kind''' is the type of a type constructor or, less commonly, the type of a higher-order type operator. A kind system is essentially a simply typed lambda calculus 'one level up,' endowed with a primitive type, denoted * and called 'type,' which is the kind of any (monomorphic) data type."<br />
<br />
Ordinary types have kind <TT>*</TT>. Type constructors have kind <TT>P -> Q</TT>, where <TT>P</TT> and <TT>Q</TT> are kinds. For instance:<br />
<br />
Int :: *<br />
Maybe :: * -> *<br />
Maybe Bool :: *<br />
a -> a :: *<br />
[] :: * -> *<br />
(->) :: * -> * -> *<br />
<br />
In Haskell 98, <TT>*</TT> is the only '''inhabited kind''', that is, all values have types of kind <TT>*</TT>. GHC introduces another inhabited kind, <TT>#</TT>, for [[unlifted type]]s.<br />
<br />
= See also =<br />
<br />
* [[GHC/Kinds]]<br />
* [http://hackage.haskell.org/trac/ghc/wiki/IntermediateTypes#KindsareTypes Kinds ?, ??, # and (#)]<br />
* [[Books#Foundations|Pierce, Benjamin. ''Types and Programming Languages'']].<br />
<br />
[[Category:Language]]</div>Takenobu.hs