More LambdaConf work
This commit is contained in:
parent
f20c93bdc6
commit
61ddfeb73a
2 changed files with 255 additions and 2 deletions
21
reveal/lambdaconf-winter-2018-part-2.md
Normal file
21
reveal/lambdaconf-winter-2018-part-2.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
Discuss the different ways to handle exceptions in different languages.
|
||||
Leads to `ExceptT`
|
||||
Problems with transformers...
|
||||
|
||||
* https://www.snoyman.com/reveal/monad-transformer-state
|
||||
* https://www.yesodweb.com/blog/2014/05/exceptions-cont-monads
|
||||
|
||||
Even ignoring that: `ExceptT` doesn't work thanks to async exceptions
|
||||
|
||||
* https://haskell-lang.org/library/safe-exceptions
|
||||
|
||||
Best practices therefore
|
||||
|
||||
* https://www.fpcomplete.com/blog/2016/11/exceptions-best-practices-haskell
|
||||
|
||||
Some bonus fun
|
||||
|
||||
* https://haskell-lang.org/tutorial/primitive-haskell
|
||||
* <https://wiki.haskell.org/Evaluation_order_and_state_tokens>
|
||||
|
||||
TODO Motivate the `RIO` data type and the `rio` package
|
|
@ -467,5 +467,237 @@ https://www.snoyman.com/blog/2016/12/beware-of-readfile
|
|||
|
||||
* Wants bytes? `Data.ByteString.readFile`
|
||||
* Want text? Choose an encoding!
|
||||
* `decodeUtf8With lenientDecode <$> Data.ByteString.readFile`
|
||||
*
|
||||
* `decodeUtf8With lenientDecode <$> B.readFile fp`
|
||||
* Let's get crazy
|
||||
|
||||
```haskell
|
||||
readFileUtf8 :: MonadIO m => FilePath -> m Text
|
||||
readFileUtf8 fp = do
|
||||
bs <- readFileBinary fp
|
||||
case decodeUtf8' bs of
|
||||
Left e -> throwIO $ ReadFileUtf8Exception fp e
|
||||
Right text -> return text
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Writing a file
|
||||
|
||||
* No need to worry about char enc problems
|
||||
* `Data.ByteString.writeFile`
|
||||
* Have text? Choose an encoding!
|
||||
* `B.writeFile fp $ encodeUtf8 text`
|
||||
|
||||
----
|
||||
|
||||
## Copy a file
|
||||
|
||||
What's wrong with this code?
|
||||
|
||||
```haskell
|
||||
bs <- B.readFile inputFile
|
||||
B.writeFile outputFile bs
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Streaming
|
||||
|
||||
Here's a conduit solution
|
||||
|
||||
```haskell
|
||||
runConduitRes $ sourceFile inputFile
|
||||
.| sinkFile outputFile
|
||||
```
|
||||
|
||||
Or without `ResourceT`:
|
||||
|
||||
```haskell
|
||||
withSourceFile inputFile $ \src ->
|
||||
withSinkFile outputFile $ \sink ->
|
||||
runConduit $ src .| sink
|
||||
```
|
||||
|
||||
Why with pattern? We'll talk exceptions later
|
||||
|
||||
---
|
||||
|
||||
## Generating large output
|
||||
|
||||
What's wrong with this code?
|
||||
|
||||
```haskell
|
||||
odds :: [Int]
|
||||
odds = [1, 3..]
|
||||
|
||||
toLine :: Int -> String
|
||||
toLine i = show i ++ "\n"
|
||||
|
||||
toLines :: [Int] -> String
|
||||
toLines = foldr (\i rest -> toLine i ++ rest) ""
|
||||
|
||||
main :: IO ()
|
||||
main = putStr $ toLines $ take 1000 odds
|
||||
```
|
||||
|
||||
__Strings!__
|
||||
|
||||
----
|
||||
|
||||
## Strict ByteString
|
||||
|
||||
```haskell
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString.Char8 as B8
|
||||
import Data.Monoid ((<>))
|
||||
|
||||
odds = [1, 3..]
|
||||
|
||||
toLine :: Int -> ByteString
|
||||
toLine i = B8.pack (show i) <> "\n"
|
||||
|
||||
toLines :: [Int] -> ByteString
|
||||
toLines = foldr (\i rest -> toLine i <> rest) B8.empty
|
||||
|
||||
main = B8.putStr $ toLines $ take 1000 odds
|
||||
```
|
||||
|
||||
Problem? Quadratic complexity
|
||||
|
||||
----
|
||||
|
||||
## Lazy ByteString
|
||||
|
||||
Avoid the buffer copies
|
||||
|
||||
```haskell
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
import Data.ByteString.Lazy (ByteString)
|
||||
import qualified Data.ByteString.Lazy.Char8 as BL8
|
||||
import Data.Monoid ((<>))
|
||||
|
||||
odds = [1, 3..]
|
||||
|
||||
toLine :: Int -> ByteString
|
||||
toLine i = BL8.pack (show i) <> "\n"
|
||||
|
||||
toLines :: [Int] -> ByteString
|
||||
toLines = foldr (\i rest -> toLine i <> rest) BL8.empty
|
||||
|
||||
main = BL8.putStr $ toLines $ take 1000 odds
|
||||
```
|
||||
|
||||
Still quadratic :(
|
||||
|
||||
----
|
||||
|
||||
## Builders
|
||||
|
||||
Single-copy data structure, efficient `Handle` interaction
|
||||
|
||||
```haskell
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
import Data.ByteString.Builder (Builder, intDec, hPutBuilder)
|
||||
import System.IO (stdout)
|
||||
import Data.Monoid ((<>))
|
||||
|
||||
odds = [1, 3..]
|
||||
|
||||
toLine :: Int -> Builder
|
||||
toLine i = intDec i <> "\n"
|
||||
|
||||
toLines :: [Int] -> Builder
|
||||
toLines = foldr (\i rest -> toLine i <> rest) mempty
|
||||
|
||||
main = hPutBuilder stdout $ toLines $ take 1000 odds
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Text builders
|
||||
|
||||
* Text also has a builder
|
||||
* Much less useful overall, no direct output capabilities
|
||||
* Downside to ByteString builders: have to assume a character encoding
|
||||
* For console, may be a problem, but great for network or file I/O
|
||||
|
||||
---
|
||||
|
||||
## Networking
|
||||
|
||||
* Low level libraries like network
|
||||
* Use the `Network.Socket` API!
|
||||
* conduit-based helper functions on top of that
|
||||
* WAI and Warp for web servers
|
||||
* http-conduit for web clients
|
||||
* Many other libraries out there too
|
||||
|
||||
----
|
||||
|
||||
## Web server
|
||||
|
||||
* Lots of details here: <https://github.com/fpco/applied-haskell/blob/master/web-services.md>
|
||||
* Who wants to go down the rabbit hole?
|
||||
|
||||
----
|
||||
|
||||
## Web client
|
||||
|
||||
* <https://haskell-lang.org/library/http-client>
|
||||
* Optional rabbit hole again
|
||||
|
||||
----
|
||||
|
||||
## Network server with conduit
|
||||
|
||||
* FIXME include some code samples
|
||||
|
||||
---
|
||||
|
||||
## Side adventure: unliftio
|
||||
|
||||
* Many more details on the motivation tomorrow
|
||||
* Two packages
|
||||
* unliftio-core provides a typeclass
|
||||
* unliftio wraps a bunch of libraries with that type class
|
||||
* If it's in unliftio: it's good to use, do it!
|
||||
* Epic foreshadowment for tomorrow's presentation :)
|
||||
|
||||
---
|
||||
|
||||
## Concurrency
|
||||
|
||||
* FIXME UnliftIO.Async
|
||||
* https://haskell-lang.org/library/async
|
||||
|
||||
---
|
||||
|
||||
## Mutable data
|
||||
|
||||
* FIXME
|
||||
* https://github.com/fpco/applied-haskell/blob/master/mutable-variables.md
|
||||
|
||||
---
|
||||
|
||||
## Exception handling
|
||||
|
||||
* Documentation still out of date
|
||||
* We'll cover the why of things tomorrow
|
||||
* Short answer: use `UnliftIO.Exception`
|
||||
|
||||
---
|
||||
|
||||
## External processes
|
||||
|
||||
* FIXME typed-process
|
||||
* https://haskell-lang.org/library/typed-process
|
||||
|
||||
---
|
||||
|
||||
## Random grab bag
|
||||
|
||||
* Typeclassopedia FIXME add link
|
||||
* <https://haskell-lang.org/tutorial/operators>
|
||||
* <https://haskell-lang.org/tutorial/synonyms>
|
||||
* <https://haskell-lang.org/library/optparse-applicative>
|
||||
|
|
Loading…
Reference in a new issue