Difference between pages "IO, partible-style" and "IRC channel"
m (Small change of formatting) |
(update to point to irc.libera.chat) |
||
Line 1: | Line 1: | ||
+ | Internet Relay Chat is a worldwide text chat service with many thousands |
||
+ | of users among various irc networks. |
||
+ | The Freenode IRC network used to host the very large #haskell channel, and we've had |
||
− | <i><code>IO</code> is the [monadic type] you cannot avoid.</i> |
||
+ | up to 1046 |
||
− | <tt> |
||
+ | concurrent users, making the channel consistently |
||
− | * [https://image.slidesharecdn.com/functionalconf2019-whyishaskellsohard2-191116135003/95/why-is-haskell-so-hard-and-how-to-deal-with-it-53-638.jpg Why Haskell is so HARD? (And how to deal with it)]; Saurabh Nanda. |
||
+ | [https://netsplit.de/channels/details.php?room=%23haskell&net=freenode one of the most popular] |
||
− | </tt> |
||
+ | of the thousands of channels on freenode. One famous |
||
+ | resident is [[Lambdabot]], another is [http://hpaste.org hpaste] (see |
||
+ | the [[#Bots|Bots]] section below). |
||
+ | As of May 19 2021, the #haskell channel and associated channels began to migrate to https://libera.chat/ . This process is still underway, but at this point it is recommended to join the channel there, and _not_ freenode. |
||
− | ::...but you kept looking anyway, and here you are! |
||
+ | The IRC channel can be an excellent place to learn more about Haskell, |
||
− | <i> |
||
+ | and to just keep in the loop on new things in the Haskell world. Many |
||
− | [...] the input/output story for purely-functional languages was weak and unconvincing, let alone error recovery, concurrency, etc. Over the last few years, a surprising solution has emerged: the monad. I say "surprising" because anything with as exotic a name as "monad" - derived from category theory, one of the most abstract branches of mathematics - is unlikely to be very useful to red-blooded programmers. But one of the joys of functional programming is the way in which apparently-exotic theory can have a direct and practical application, and the monadic story is a good example. |
||
+ | new developments in the Haskell world first appear on the irc channel. |
||
− | </i> |
||
− | <tt> |
||
− | * [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.13.9123&rep=rep1&type=pdf Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell], Simon Peyton Jones. |
||
− | </tt> |
||
+ | Since 2009, the Haskell channel has grown large enough that we've split it in two parts: |
||
− | ::...with that (''ahem'') "joy" leading to more than a few [[Monad tutorials timeline|helpful guides about the topic]] - that monadic interface: it's abstract alright! |
||
+ | * #haskell, for all the usual things |
||
− | __TOC__ |
||
+ | * #haskell-in-depth , for those seeking in depth, or more theoretical discussion |
||
− | <sub> </sub> |
||
− | ---- |
||
+ | As always, #haskell remains the primary place for new user questions. |
||
− | === <code>IO</code>, <u>using</u> <code>OI</code> === |
||
+ | {| border="0" |
||
− | Our definition of <code>IO</code> is a type synonym: |
||
+ | |+ '''#haskell visualized''' |
||
+ | |- |
||
+ | | [[Image:Haskell-current.png|thumb|The social graph, Jan 2008]] |
||
+ | | [[Image:Irc-raw.png|thumb|Daily traffic since 2004]] |
||
+ | |- |
||
+ | | [[Image:Nick-activity.png|thumb|Growth]] |
||
+ | | [[Image:Haskell-wordle-irc.png|thumb|Noun map]] |
||
+ | |} |
||
+ | == Getting there == |
||
− | <haskell> |
||
− | type IO a = OI -> a |
||
− | </haskell> |
||
+ | If you point your irc client to [irc://irc.libera.chat:6697 irc.libera.chat:6697 (TLS)] and then join the #haskell channel, you'll be there. Alternately, you can try a client (some listed at [https://libera.chat/guides/clients] ) which connects inside the browser. |
||
− | with <code>OI</code> being an abstract [[Plainly partible|partible]] type: |
||
+ | Example, using [http://www.irssi.org/ irssi]: |
||
− | <haskell> |
||
− | data OI a |
||
− | primitive primPartOI :: OI -> (OI, OI) |
||
+ | $ irssi -c irc.libera.chat:6697 -n myname -w mypassword |
||
− | instance Partible OI where |
||
− | + | /join #haskell |
|
− | </haskell> |
||
+ | Tip, if you're using Emacs to edit your Haskell sources then why not use it to chat about Haskell? Check out [http://www.emacswiki.org/cgi-bin/wiki/EmacsIRCClient ERC], The Emacs IRC client. Invoke it like this and follow the commands: |
||
− | Like <code>primPartOI</code>, most other primitives for the <code>OI</code> type also accept an <code>OI</code>-value as their last (or only) argument e.g: |
||
+ | M-x erc-select |
||
− | <haskell> |
||
+ | ... |
||
− | primitive primGetChar :: OI -> Char |
||
+ | /join #haskell |
||
− | primitive primPutChar :: Char -> OI -> () |
||
− | ⋮ |
||
− | </haskell> |
||
+ | [[Image:Irc--haskell-screenshot.png|frame|A screenshot of an irssi session in #haskell]] |
||
− | Borrowing the running example from Philip Wadler's [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf How to Declare an Imperative]: |
||
+ | == Principles == |
||
− | <haskell> |
||
− | echo :: OI -> () |
||
− | echo u = let !(u1:u2:u3:_) = parts u |
||
− | !c = primGetChar u1 in |
||
− | if c == '\n' then |
||
− | () |
||
− | else |
||
− | let !_ = primPutChar c u2 |
||
− | in echo u3 |
||
− | </haskell> |
||
+ | The #haskell channel is a very friendly, welcoming place to hang out, |
||
− | Wadler also provides an [https://www.smlnj.org/sml.html SML] version: |
||
+ | teach and learn. The goal of #haskell is to encourage learning and |
||
+ | discussion of Haskell, functional programming, and programming in |
||
+ | general. As part of this we welcome newbies, and encourage teaching of |
||
+ | the language. |
||
+ | Part of the #haskell success comes from the fact that the community |
||
− | <pre> |
||
+ | is quite tight knit — we know each other — it's not just a homework |
||
− | val echoML : unit -> unit |
||
+ | channel. As a result, many collaborative projects have arisen between |
||
− | fun echoML () = let val c = getcML () in |
||
+ | Haskell irc channel citizens. |
||
− | if c = #"\n" then |
||
− | () |
||
− | else |
||
− | (putcML c; echoML ()) |
||
− | end |
||
− | </pre> |
||
+ | To maintain the friendly, open culture, the following is required: |
||
− | in which we replace SML's sequencing operator <code>;</code>: |
||
+ | * Low to zero tolerance for ridiculing questions. Insulting new users is unacceptable. New Haskell users should feel entirely comfortable asking questions. |
||
− | <pre> |
||
− | val echoML : unit -> unit |
||
− | fun echoML () = let val c = getcML () in |
||
− | if c = #"\n" then |
||
− | () |
||
− | else |
||
− | let val _ = putcML c in |
||
− | echoML () |
||
− | end |
||
− | end |
||
− | </pre> |
||
+ | * Helpful answers should be encouraged with <code>name++</code> karma points, in public, as a reward for providing a good answer. |
||
− | If we compare it to our Haskell version: |
||
+ | * Avoid getting frustrated by negative comments and ambiguous questions. Approach them by asking for details (i.e. [http://en.wikipedia.org/wiki/Socratic_method Socratic questioning]), rather than challenging the competence of the writer (ad hominem). As the channel grows, we see a diverse range of people with different programming backgrounds getting accustomed to Haskell. Be patient and take satisfaction from spreading knowledge. |
||
− | {| |
||
− | |<haskell> |
||
− | echo :: OI -> () |
||
− | echo u = let !(u1:u2:u3:_) = parts u |
||
− | !c = primGetChar u1 in |
||
− | if c == '\n' then |
||
− | () |
||
− | else |
||
− | let !_ = primPutChar c u2 |
||
− | in echo u3 |
||
+ | == History == |
||
− | -- |
||
− | </haskell> |
||
− | |<pre> |
||
− | val echoML : unit -> unit |
||
− | fun echoML () = |
||
− | let val c = getcML () in |
||
− | if c = #"\n" then |
||
− | () |
||
− | else |
||
− | let val _ = putcML c in |
||
− | echoML () |
||
− | end |
||
− | end |
||
− | </pre> |
||
− | |} |
||
− | ...we can now see just how similar the two versions of <code>echo</code> really are: apart from the obvious changes of syntax, the Haskell version replaces all use of <code>unit</code>-values with <code>OI</code>-values, and adds an extra call to <code>parts</code> to provide them. |
||
+ | The #haskell channel appeared in the late 90s, and really got going |
||
− | So there you have it: for the price of some extra calls and bindings, we can have SML-style I/O in Haskell. Furthermore, as SML has been available since 1997, there should be plenty of I/O tutorials to choose from... |
||
+ | in early 2001, with the help of Shae Erisson (aka shapr). |
||
+ | == Related channels == |
||
− | At this point, you may be tempted to try something like: |
||
+ | In addition to the main Haskell channel there are also: |
||
− | <pre> |
||
− | type IO a = () -> a |
||
+ | === Language/Country specific === |
||
− | primitive might_get_Char :: () -> Char |
||
− | primitive might_put_Char :: Char -> () |
||
− | ⋮ |
||
− | </pre> |
||
+ | Language channels are consolidated into the "#haskell-" namespace. Eventually the language channels below listed with "#haskell." will have to move. |
||
− | While this ''might'' work in some situations, it's unreliable in general. Why? |
||
+ | {| border="1" cellspacing="0" cellpadding="5" |
||
− | * ''Short answer'': unlike SML, Haskell's nonstrict evaluation means expressions should be referentially transparent. |
||
+ | ! Channel |
||
− | * ''Long answer'': read section 2.2 (pages 4-5) of Wadler's [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf paper]. |
||
+ | ! Purpose |
||
− | * ''Longer answer'': read Lennart Augustsson's [https://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-in.html More points for lazy evaluation]. |
||
+ | |- |
||
− | * ''Extended answer'': read John Hughes's [https://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf Why Functional Programming Matters]. |
||
+ | | style="width: 20%;" | #haskell-br |
||
− | |||
+ | | Brazilian Portuguese (pt_BR) speakers |
||
− | But - if after all that - you're still not convinced, then perhaps you'll be happier programming in [https://www.smlnj.org/sml.html SML]... |
||
+ | |- |
||
− | |||
+ | | #haskell.cz |
||
− | |||
+ | | Czech speakers (UTF-8) |
||
− | ...you're still here: ''nice!'' Now for a small example - here's <code>interact</code>, using those <code>OI</code>-based definitions: |
||
+ | |- |
||
− | |||
− | + | | #haskell.de |
|
+ | | German speakers |
||
− | interact :: (String -> String) -> OI -> () |
||
+ | |- |
||
− | interact f v = let !(u1, u2) = part v |
||
+ | | #haskell.dut |
||
− | gets = map primGetChar $ parts u1 |
||
+ | | Dutch speakers |
||
− | puts s = foldr (\!_ -> id) () $ zipWith primPutChar s $ parts u2 |
||
+ | |- |
||
− | in |
||
+ | | #haskell.es |
||
− | puts $ f $ gets |
||
+ | | Spanish speakers |
||
− | </haskell> |
||
+ | |- |
||
− | <sub> </sub> |
||
+ | | #haskell.fi |
||
− | ---- |
||
+ | | Finnish speakers |
||
− | === <u>Some annoyances</u> === |
||
+ | |- |
||
− | |||
+ | | #haskell-fr |
||
− | * ''Extra parameters and arguments'' - As noted in Paul Hudak and Raman S. Sundaresh's [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.695&rep=rep1&type=pdf On the Expressiveness of Purely Functional I/O Systems], passing around all those <code>OI</code>-values ''correctly'' can be tedious for large definitions. |
||
+ | | French speakers (note the hyphen! in the channel name) |
||
− | |||
+ | |- |
||
− | * ''Polymorphic references'' - It's been known for a very long time in the SML community that naive declarations for operations using ''mutable references'' breaks type safety: |
||
+ | | #haskell.hr |
||
− | |||
+ | | Croatian speakers |
||
− | :{| |
||
+ | |- |
||
− | |<pre> |
||
+ | | #haskell-id |
||
− | primitive newPolyRef :: a -> OI -> PolyRef a |
||
+ | | Indonesian speakers (note the hyphen! in the channel name) |
||
− | primitive readPolyRef :: PolyRef a -> OI -> a |
||
+ | |- |
||
− | primitive writePolyRef :: PolyRef a -> a -> OI -> () |
||
+ | | #haskell-it |
||
+ | | Italian speakers (note the hyphen! in the channel name) |
||
+ | |- |
||
+ | | #haskell.jp |
||
+ | | Japanese speakers |
||
+ | |- |
||
+ | | #haskell.scandinavian |
||
+ | | Scandinavian speakers |
||
+ | |- |
||
+ | | #haskell-kr |
||
+ | | Korean speakers |
||
+ | |- |
||
+ | | #haskell.no |
||
+ | | Norwegian speakers |
||
+ | |- |
||
+ | | #haskell.pt |
||
+ | | Portuguese speakers |
||
+ | |- |
||
+ | | #haskell-pl |
||
+ | | Polish speakers |
||
+ | |- |
||
+ | | #haskell.ru |
||
+ | | Russian speakers. Seems that most of them migrated to Jabber conference (haskell@conference.jabber.ru). |
||
+ | |- |
||
+ | | #haskell_ru |
||
+ | | Russian speakers again, in UTF-8. For those, who prefer good ol' IRC channel with a lambdabot. |
||
+ | |- |
||
+ | | #haskell-ro |
||
+ | | Romanian speakers. |
||
+ | |- |
||
+ | | #haskell.se |
||
+ | | Swedish speakers |
||
+ | |- |
||
+ | | #haskell.tw |
||
+ | | Chinese speakers (mainly in Taiwan) |
||
+ | |- |
||
+ | | #haskell.vn |
||
+ | | Vietnamese speakers |
||
+ | |- |
||
+ | | #chicagohaskell |
||
+ | | [http://chicagohaskell.com Chicago Haskell] programmers group |
||
+ | |} |
||
+ | === Platform-specific === |
||
− | kah_BOOM u = let … |
||
+ | {| border="1" cellspacing="0" cellpadding="5" |
||
− | !vehicle = newPolyRef undefined u1 |
||
+ | ! Channel |
||
− | !_ = writePolyRef ("0" :: [Char]) u2 |
||
+ | ! Purpose |
||
− | !crash = readPolyRef vehicle u3 |
||
+ | |- |
||
− | burn = 1 :: Int |
||
+ | | style="width: 20%;" | #haskell-beginners |
||
− | in |
||
+ | | Haskell people focused on teaching and learning Haskell, not just beginners. |
||
− | crash + burn |
||
+ | |- |
||
− | </pre> |
||
+ | | #haskell-offtopic |
||
+ | | Haskell people talking about anything except Haskell itself (no TLS required) |
||
+ | |- |
||
+ | | #haskell-blah |
||
+ | | Haskell people talking about anything except Haskell itself (TLS required) |
||
+ | |- |
||
+ | | #haskell-game |
||
+ | | The hub for Haskell-based [[Game Development|game development]] |
||
+ | |- |
||
+ | | #haskell-in-depth |
||
+ | | slower paced discussion of use, theory, implementation etc with no monad tutorials! |
||
+ | |- |
||
+ | | #haskell-iphone |
||
+ | | Haskell-based [[iPhone]] development |
||
+ | |- |
||
+ | | #haskell-apple |
||
+ | | projects that target iOS or OS X using Haskell. |
||
+ | |- |
||
+ | | #haskell-lisp |
||
+ | | [[Haskell Lisp]] - projects that are creating Lisps written in Haskell, or Haskell implementations written in Lisps. |
||
+ | |- |
||
+ | | #haskell-llvm |
||
+ | | For projects using Haskell and LLVM |
||
+ | |- |
||
+ | | #haskell-overflow |
||
+ | | Overflow conversations |
||
+ | |- |
||
+ | | #haskell-web |
||
+ | | Friendly, practical discussion of haskell web app/framework/server development |
||
+ | |- |
||
+ | | #haskell-robotics |
||
+ | | Discussion about the use of Haskell for robotics applications. |
||
+ | |- |
||
+ | | #arch-haskell |
||
+ | | [[Arch Linux]]/ specific Haskell conversations |
||
+ | |- |
||
+ | | #fedora-haskell |
||
+ | | [https://fedoraproject.org/wiki/Haskell Fedora] Haskell SIG |
||
+ | |- |
||
+ | | #gentoo-haskell |
||
+ | | [[Gentoo]]/Linux specific Haskell conversations |
||
|} |
|} |
||
+ | === Projects using haskell === |
||
− | :SML's solution is to make all mutable references ''monomorphic'' through the use of dedicated syntax: |
||
+ | {| border="1" cellspacing="0" cellpadding="5" |
||
− | |||
+ | ! Channel |
||
− | :{| |
||
+ | ! Purpose |
||
− | |<pre> |
||
+ | |- |
||
− | let val r = ref (…) |
||
− | + | | style="width: 20%;" | #darcs |
|
+ | | [[Darcs]] revision control system |
||
− | </pre> |
||
+ | |- |
||
+ | | #diagrams |
||
+ | | [[Diagrams]] EDSL |
||
+ | |- |
||
+ | | #hackage |
||
+ | | Haskell's software distribution infrastructure |
||
+ | |- |
||
+ | | #haskell-lens |
||
+ | | [[Lens]] discussions |
||
+ | |- |
||
+ | | #haskell-stack |
||
+ | | [https://github.com/commercialhaskell/stack/tree/master/doc Stack] discussions |
||
+ | |- |
||
+ | | #happs |
||
+ | | [http://happstack.com Happstack] web framework |
||
+ | |- |
||
+ | | #hledger |
||
+ | | [http://hledger.org hledger] accounting tools and library |
||
+ | |- |
||
+ | | #leksah |
||
+ | | [http://leksah.org Leksah] IDE for Haskell development |
||
+ | |- |
||
+ | | #snowdrift |
||
+ | | [https://snowdrift.coop Snowdrift.coop] Yesod-based web platform for funding free/libre/open works, welcomes Haskell volunteer devs including beginners |
||
+ | |- |
||
+ | | #snapframework |
||
+ | | [http://snapframework.com/ Snap] web framework |
||
+ | |- |
||
+ | | #xmonad |
||
+ | | [http://xmonad.org Xmonad] tiling window manager |
||
+ | |- |
||
+ | | #yesod |
||
+ | | [http://yesodweb.com Yesod] web framework |
||
+ | |- |
||
+ | | #yampa |
||
+ | | [https://wiki.haskell.org/Yampa Yampa] Arrowized FRP |
||
|} |
|} |
||
+ | == Logs == |
||
− | :One alternative for Haskell would be to extend type signatures to support [[Monomorphism by annotation of type variables|monomorphic type-variables]]: |
||
+ | '''Logs''' are kept at http://tunes.org/~nef/logs/haskell/ |
||
− | :<haskell> |
||
− | primitive newIORef :: monomo a . a -> OI -> IORef a |
||
− | primitive readIORef :: monomo a . IORef a -> OI -> a |
||
− | primitive writeIORef :: monomo a . IORef a -> a -> OI -> () |
||
+ | <!-- anywhere else? http://ircbrowse.net/browse/haskell is a goner, apparently --> |
||
− | {- would be rejected by the extended type system: |
||
− | kah_BOOM u = let !(u1:u2:u3:_) = parts u |
||
− | !vehicle = newIORef undefined u1 -- vehicle :: monomo a . IORef a |
||
− | !_ = writeIORef ("0" :: [Char]) u2 -- vehicle :: IORef [Char] |
||
− | !crash = readIORef vehicle u3 -- vehicle :: IORef [Char] ≠ IORef Int |
||
− | burn = 1 :: Int |
||
− | in |
||
− | crash + burn |
||
− | -} |
||
− | </haskell> |
||
+ | == Bots == |
||
− | :In standard Haskell, one of the few places this already occurs (albeit implicitly) is the parameters of a function: |
||
+ | There are various bots on the channel. Their names and usage are described here. |
||
− | :<haskell> |
||
− | {- will be rejected by the standard Haskell type system |
||
+ | === lambdabot === |
||
− | ker_plunk f = (f True, f 'b') |
||
+ | [[Lambdabot]] is both the name of a software package and a bot on the channel. The bot is operated by IRC user <code>int-e</code> and provides many useful services for visitors to the IRC channel. You can interact with it in a private chat or publicly in any channel where it appears (#haskell and a number of others). It is available as a haskell package and can be integrated into ghci. Details on the software are found on a [[Lambdabot|separate wiki page]]. |
||
− | -} |
||
− | </haskell> |
||
− | ---- |
||
− | === <u>One solution</u> === |
||
+ | Here is its interface for the IRC user: |
||
− | * ''Extra parameters and arguments'' - What is needed is a succinct interface to "hide the plumbing" used to pass around <code>OI</code>-values: |
||
+ | lambdabot's commands are prepended by a '@' sign. |
||
− | :<haskell> |
||
− | instance Monad ((->) OI) where |
||
− | return x = \u -> case part u of !_ -> x |
||
− | m >>= k = \u -> case part u of |
||
− | (u1, u2) -> case m u1 of |
||
− | !x -> k x u2 |
||
− | </haskell> |
||
+ | {| border="1" cellspacing="0" cellpadding="5" |
||
− | * ''Polymorphic references'' - we now make <code>IO</code> into an ''abstract data type'': |
||
+ | ! Command |
||
− | |||
+ | ! Usage |
||
− | :<haskell> |
||
+ | |- |
||
− | module Abstract.IO |
||
+ | | @help |
||
− | ( |
||
+ | | display help to other commands, but help text is not available for all commands. |
||
− | Monad (..), |
||
+ | |- |
||
− | getChar, putChar, … |
||
+ | | @where TOPIC (aliases: @what, @url) <br> @where ? <br> @where+ TOPIC NEWTEXT <br> @where+ TOPIC |
||
− | newIORef, readIORef, writeIORef, |
||
+ | | show brief info about some TOPIC <br> list some useful topics (paste, cabalstackhelp, ...) <br> set/update a topic (check for collisions first with @where TOPIC) <br> delete a topic |
||
− | ⋮ |
||
+ | |- |
||
− | ) |
||
+ | | @type EXPR or ':t' EXPR |
||
− | where |
||
+ | | shows the type of an expression |
||
− | |||
+ | |- |
||
− | instance Monad ((->) OI) where |
||
+ | | @kind TYPECONSTRUCTOR |
||
− | return x = \u -> case part u of !_ -> x |
||
+ | | shows the kind of a type constructor |
||
− | m >>= k = \u -> case part u of |
||
+ | |- |
||
− | (u1, u2) -> case m u1 of |
||
+ | | @run EXPR or '>' EXPR |
||
− | !x -> k x u2 |
||
+ | | evaluates EXPR |
||
− | |||
+ | |- |
||
− | getChar :: IO Char |
||
+ | | @pl FUNCTION |
||
− | getChar = primGetChar |
||
+ | | shows a [[pointfree]] version of FUNCTION |
||
− | |||
+ | |- |
||
− | putChar :: Char -> IO () |
||
+ | | @pointful FUNCTION or '@unpl' FUNCTION |
||
− | putChar = primPutChar |
||
+ | | shows a 'pointful' version of FUNCTION |
||
− | |||
+ | |- |
||
− | newIORef :: a -> IO (IORef a) |
||
+ | | @tell <nick> <msg> -- same as @ask |
||
− | newIORef = primNewIORef |
||
+ | | Next time <nick> speaks in channel they will be notified they have a message pending and how to receive it. |
||
− | |||
− | readIORef :: IORef a -> IO a |
||
− | readIORef = primReadIORef |
||
− | |||
− | writeIORef :: IORef a -> a -> IO () |
||
− | writeIORef = primWriteIORef |
||
− | |||
− | |||
− | -- these are now local, private entities -- |
||
− | type IO a = OI -> a |
||
− | |||
− | data OI a |
||
− | primitive primPartOI :: OI -> (OI, OI) |
||
− | |||
− | primitive primGetChar :: OI -> Char |
||
− | primitive primPutChar :: Char -> OI -> () |
||
− | ⋮ |
||
− | |||
− | data IORef |
||
− | primitive primNewIORef :: a -> OI -> IORef a |
||
− | primitive primReadIORef :: IORef a -> OI -> a |
||
− | primitive primWriteIORef :: IORef a -> a -> OI -> () |
||
− | ⋮ |
||
− | |||
− | </haskell> |
||
− | |||
− | :With the <code>IO</code> type now made abstract, the only way to use <code>IO</code>-values is by using: |
||
− | |||
− | :* the visible <code>IO</code> operations: <code>getChar</code>, <code>putChar</code>, etc. |
||
− | :* the monadic interface - <code>Monad(return, (>>=), …)</code> (or via Haskell's <code>do</code>-notation). |
||
− | |||
− | :The key here is the type of <code>(>>=)</code>, for <code>IO</code>-values: |
||
− | |||
− | :<haskell> |
||
− | (>>=) :: IO a -> (a -> IO b) -> IO b |
||
− | </haskell> |
||
− | |||
− | :in particular, the type of the second argument: |
||
− | |||
− | ::{| |
||
− | |<haskell> |
||
− | (a -> IO b) |
||
− | </haskell> |
||
|} |
|} |
||
+ | See also: |
||
− | :...it's a function, so the value it receives will be rendered monomorphic in the function's result (of type <code>IO b</code>). |
||
+ | * http://silicon.int-e.eu/lambdabot/State/where - @where db snapshot, updated every few minutes |
||
− | |||
+ | * https://github.com/simonmichael/lambdabot-where - git repo and .tsv version of the @where db, updated occasionally |
||
− | :As <code>(>>=)</code> is now the only <code>IO</code> operation which can retrieve a result from an <code>IO</code>-value, mutable references (<code>IORef …</code>) simply cannot be used polymorphically. |
||
− | ---- |
||
− | === <u>GHC's solution</u> === |
||
− | <sub> </sub> |
||
− | <haskell> |
||
− | newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #)) |
||
− | </haskell> |
||
− | |||
− | ...you may have noticed that we've already made liberal use of one Haskell extension - [https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/bang-patterns.html bang-patterns] - and it would be useful to stay as close as possible to standard Haskell, so we'll simplify matters: |
||
− | |||
− | <haskell> |
||
− | newtype IO a = IO (IOState -> (IOState, a)) -- unboxed-tuple replaced by standard one |
||
− | |||
− | type IOState = State# RealWorld |
||
− | </haskell> |
||
− | |||
− | Now to make the changes: |
||
− | |||
− | * ''to the type'' - <code>IOState</code> uses an <code>OI</code>-value: |
||
− | |||
− | :<haskell> |
||
− | newtype IOState = IOS OI |
||
− | </haskell> |
||
− | |||
− | * ''to the I/O-specific operations'' - each one will use the <code>OI</code>-value in the initial state to provide two new <code>OI</code>-values: one to make up the final state; the other being used by the <code>OI</code>-primitive: |
||
− | |||
− | :<haskell> |
||
− | getChar :: IO Char |
||
− | getChar = IO $ \(IOS u) -> let !(u1, u2) = parts u |
||
− | !c = primGetChar u1 |
||
− | in (IOS u2, c) |
||
− | |||
− | putChar :: Char -> IO () |
||
− | putChar c = IO $ \(IOS u) -> let !(u1, u2) = parts u |
||
− | !t = primPutChar c u1 |
||
− | in (IOS u2, t) |
||
− | |||
− | -- etc. |
||
− | </haskell> |
||
− | |||
− | * ''to the overloaded operations'' - you've probably seen it all before: |
||
− | |||
− | :<haskell> |
||
− | instance Monad IO where |
||
− | return x = IO $ \!s -> (s, x) |
||
− | IO m >>= k = IO $ \!s -> let !(s', x) = m s |
||
− | !IO w = k x |
||
− | in w s' |
||
− | </haskell> |
||
− | |||
− | :(...if you haven't: it's ye ol' <del>''pass-the-planet''</del> state-passing technique.) |
||
+ | === yahb === |
||
− | One aspect which doesn't change is <code>IO</code> and its operations being abstract. In fact, the need is even more pressing: in addition to preventing the misuse of certain <code>OI</code>-operations, being an abstract data type prevents <code>IOState</code>-values from being erroneously reused. |
||
+ | If lambdabot doesn't cut it for you, there is a bot called yahb which runs your request in an actual GHCi prompt, so you can use IO. |
||
− | ---- |
||
− | === <u>Conclusions</u> === |
||
+ | Try e.g. <tt>% readFile "/proc/self/environ"</tt> |
||
− | * ''Why is Haskell I/O monadic'' - to avoid having to use extra arguments and parameters ''everywhere''. |
||
+ | === hackage === |
||
− | * ''Why is Haskell I/O abstract'' - to ensure I/O works as intended, by preventing the misuse of internal data. |
||
+ | The hackage bot, when running, provides real-time notifications of new package uploads to [http://hackage.haskell.org Hackage]. |
||
+ | == Locations == |
||
− | * ''Why is Haskell I/O unusual'' - because of Haskell's ''nonstrict evaluation'' and thus its focus on ''referential transparency'', contrary to most other programming languages. |
||
+ | To get an overview of where everybody on the channel might |
||
− | ---- |
||
+ | be, physically, please visit [[Haskell user locations]]. |
||
− | === <u>Further reading</u> === |
||
− | If you've managed to get all the way to here, [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.52.3656&rep=rep1&type=pdf State in Haskell] by John Launchbury and Simon Peyton Jones is also worth reading, if you're interested in how GHC eventually arrived at its current definition of <code>IO</code>. |
||
− | [[Category: |
+ | [[Category:Community]] |
Revision as of 15:57, 19 May 2021
Internet Relay Chat is a worldwide text chat service with many thousands of users among various irc networks.
The Freenode IRC network used to host the very large #haskell channel, and we've had up to 1046 concurrent users, making the channel consistently one of the most popular of the thousands of channels on freenode. One famous resident is Lambdabot, another is hpaste (see the Bots section below).
As of May 19 2021, the #haskell channel and associated channels began to migrate to https://libera.chat/ . This process is still underway, but at this point it is recommended to join the channel there, and _not_ freenode.
The IRC channel can be an excellent place to learn more about Haskell, and to just keep in the loop on new things in the Haskell world. Many new developments in the Haskell world first appear on the irc channel.
Since 2009, the Haskell channel has grown large enough that we've split it in two parts:
- #haskell, for all the usual things
- #haskell-in-depth , for those seeking in depth, or more theoretical discussion
As always, #haskell remains the primary place for new user questions.
Getting there
If you point your irc client to irc.libera.chat:6697 (TLS) and then join the #haskell channel, you'll be there. Alternately, you can try a client (some listed at [1] ) which connects inside the browser.
Example, using irssi:
$ irssi -c irc.libera.chat:6697 -n myname -w mypassword /join #haskell
Tip, if you're using Emacs to edit your Haskell sources then why not use it to chat about Haskell? Check out ERC, The Emacs IRC client. Invoke it like this and follow the commands:
M-x erc-select ... /join #haskell
Principles
The #haskell channel is a very friendly, welcoming place to hang out, teach and learn. The goal of #haskell is to encourage learning and discussion of Haskell, functional programming, and programming in general. As part of this we welcome newbies, and encourage teaching of the language.
Part of the #haskell success comes from the fact that the community is quite tight knit — we know each other — it's not just a homework channel. As a result, many collaborative projects have arisen between Haskell irc channel citizens.
To maintain the friendly, open culture, the following is required:
- Low to zero tolerance for ridiculing questions. Insulting new users is unacceptable. New Haskell users should feel entirely comfortable asking questions.
- Helpful answers should be encouraged with
name++
karma points, in public, as a reward for providing a good answer.
- Avoid getting frustrated by negative comments and ambiguous questions. Approach them by asking for details (i.e. Socratic questioning), rather than challenging the competence of the writer (ad hominem). As the channel grows, we see a diverse range of people with different programming backgrounds getting accustomed to Haskell. Be patient and take satisfaction from spreading knowledge.
History
The #haskell channel appeared in the late 90s, and really got going in early 2001, with the help of Shae Erisson (aka shapr).
Related channels
In addition to the main Haskell channel there are also:
Language/Country specific
Language channels are consolidated into the "#haskell-" namespace. Eventually the language channels below listed with "#haskell." will have to move.
Channel | Purpose |
---|---|
#haskell-br | Brazilian Portuguese (pt_BR) speakers |
#haskell.cz | Czech speakers (UTF-8) |
#haskell.de | German speakers |
#haskell.dut | Dutch speakers |
#haskell.es | Spanish speakers |
#haskell.fi | Finnish speakers |
#haskell-fr | French speakers (note the hyphen! in the channel name) |
#haskell.hr | Croatian speakers |
#haskell-id | Indonesian speakers (note the hyphen! in the channel name) |
#haskell-it | Italian speakers (note the hyphen! in the channel name) |
#haskell.jp | Japanese speakers |
#haskell.scandinavian | Scandinavian speakers |
#haskell-kr | Korean speakers |
#haskell.no | Norwegian speakers |
#haskell.pt | Portuguese speakers |
#haskell-pl | Polish speakers |
#haskell.ru | Russian speakers. Seems that most of them migrated to Jabber conference (haskell@conference.jabber.ru). |
#haskell_ru | Russian speakers again, in UTF-8. For those, who prefer good ol' IRC channel with a lambdabot. |
#haskell-ro | Romanian speakers. |
#haskell.se | Swedish speakers |
#haskell.tw | Chinese speakers (mainly in Taiwan) |
#haskell.vn | Vietnamese speakers |
#chicagohaskell | Chicago Haskell programmers group |
Platform-specific
Channel | Purpose |
---|---|
#haskell-beginners | Haskell people focused on teaching and learning Haskell, not just beginners. |
#haskell-offtopic | Haskell people talking about anything except Haskell itself (no TLS required) |
#haskell-blah | Haskell people talking about anything except Haskell itself (TLS required) |
#haskell-game | The hub for Haskell-based game development |
#haskell-in-depth | slower paced discussion of use, theory, implementation etc with no monad tutorials! |
#haskell-iphone | Haskell-based iPhone development |
#haskell-apple | projects that target iOS or OS X using Haskell. |
#haskell-lisp | Haskell Lisp - projects that are creating Lisps written in Haskell, or Haskell implementations written in Lisps. |
#haskell-llvm | For projects using Haskell and LLVM |
#haskell-overflow | Overflow conversations |
#haskell-web | Friendly, practical discussion of haskell web app/framework/server development |
#haskell-robotics | Discussion about the use of Haskell for robotics applications. |
#arch-haskell | Arch Linux/ specific Haskell conversations |
#fedora-haskell | Fedora Haskell SIG |
#gentoo-haskell | Gentoo/Linux specific Haskell conversations |
Projects using haskell
Channel | Purpose |
---|---|
#darcs | Darcs revision control system |
#diagrams | Diagrams EDSL |
#hackage | Haskell's software distribution infrastructure |
#haskell-lens | Lens discussions |
#haskell-stack | Stack discussions |
#happs | Happstack web framework |
#hledger | hledger accounting tools and library |
#leksah | Leksah IDE for Haskell development |
#snowdrift | Snowdrift.coop Yesod-based web platform for funding free/libre/open works, welcomes Haskell volunteer devs including beginners |
#snapframework | Snap web framework |
#xmonad | Xmonad tiling window manager |
#yesod | Yesod web framework |
#yampa | Yampa Arrowized FRP |
Logs
Logs are kept at http://tunes.org/~nef/logs/haskell/
Bots
There are various bots on the channel. Their names and usage are described here.
lambdabot
Lambdabot is both the name of a software package and a bot on the channel. The bot is operated by IRC user int-e
and provides many useful services for visitors to the IRC channel. You can interact with it in a private chat or publicly in any channel where it appears (#haskell and a number of others). It is available as a haskell package and can be integrated into ghci. Details on the software are found on a separate wiki page.
Here is its interface for the IRC user:
lambdabot's commands are prepended by a '@' sign.
Command | Usage |
---|---|
@help | display help to other commands, but help text is not available for all commands. |
@where TOPIC (aliases: @what, @url) @where ? @where+ TOPIC NEWTEXT @where+ TOPIC |
show brief info about some TOPIC list some useful topics (paste, cabalstackhelp, ...) set/update a topic (check for collisions first with @where TOPIC) delete a topic |
@type EXPR or ':t' EXPR | shows the type of an expression |
@kind TYPECONSTRUCTOR | shows the kind of a type constructor |
@run EXPR or '>' EXPR | evaluates EXPR |
@pl FUNCTION | shows a pointfree version of FUNCTION |
@pointful FUNCTION or '@unpl' FUNCTION | shows a 'pointful' version of FUNCTION |
@tell <nick> <msg> -- same as @ask | Next time <nick> speaks in channel they will be notified they have a message pending and how to receive it. |
See also:
- http://silicon.int-e.eu/lambdabot/State/where - @where db snapshot, updated every few minutes
- https://github.com/simonmichael/lambdabot-where - git repo and .tsv version of the @where db, updated occasionally
yahb
If lambdabot doesn't cut it for you, there is a bot called yahb which runs your request in an actual GHCi prompt, so you can use IO.
Try e.g. % readFile "/proc/self/environ"
hackage
The hackage bot, when running, provides real-time notifications of new package uploads to Hackage.
Locations
To get an overview of where everybody on the channel might be, physically, please visit Haskell user locations.