Send Beginners mailing list submissions to beginners@haskell.org To subscribe or unsubscribe via the World Wide Web, visit http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners or, via email, send a message with subject or body 'help' to beginners-requ...@haskell.org
You can reach the person managing the list at beginners-ow...@haskell.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Beginners digest..." Today's Topics: 1. Re: Reproduce example in Crypto.JWT (Pietro Grandinetti) 2. Re: Understanding reason for Monad (Travis Cardwell) ---------------------------------------------------------------------- Message: 1 Date: Sun, 26 Feb 2023 14:11:15 +0000 From: Pietro Grandinetti <pietro....@hotmail.it> To: "beginners@haskell.org" <beginners@haskell.org> Subject: Re: [Haskell-beginners] Reproduce example in Crypto.JWT Message-ID: <db9p191mb1514a68c9425d81672ed1715fc...@db9p191mb1514.eurp191.prod.outlook.com> Content-Type: text/plain; charset="windows-1252" Francesco, That solved it. Would it be better to use nightly only for this package and, if so, is this possible within the package.yaml file? Thanks. ________________________________ From: Beginners <beginners-boun...@haskell.org> on behalf of Francesco Ariis <fa...@ariis.it> Sent: Sunday, February 26, 2023 1:05 PM To: beginners@haskell.org <beginners@haskell.org> Subject: Re: [Haskell-beginners] Reproduce example in Crypto.JWT Il 26 febbraio 2023 alle 11:57 Pietro Grandinetti ha scritto: > Francesco, > > Thanks. > I am using stack and the version doesn't match: `stack ls dependencies` shows > `jose 0.9`. I can't seem to find a way to upgrade it even if I set `jose >= > 0.10` in the package.yaml file: This is `jose` in stackage: https://www.stackage.org/lts-20.12/package/jose-0.9 So switching to Nightly will do —F _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20230226/47de525b/attachment-0001.html> ------------------------------ Message: 2 Date: Mon, 27 Feb 2023 20:53:28 +0900 From: Travis Cardwell <travis.cardw...@extrema.is> To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell <beginners@haskell.org> Subject: Re: [Haskell-beginners] Understanding reason for Monad Message-ID: <CACaJP_Qqkxouht=o+oq+i59e4dzjhd1va_fig1j0c4ypask...@mail.gmail.com> Content-Type: text/plain; charset="UTF-8" Hi Pietro, The example in my previous message is that of a web application where the user registration request handler needs to write to a database as well as perform logging. In a production server, connecting to a database usually requires some configuration, and a pool of database connections is kept open and reused for improved performance. Similarly, logging may require configuration that the whole application needs to use in order to log consistently, and a resource may be kept open depending on how logging is configured. The server can initialize this state and provide it to various components such as request handlers. This state is what I referred to as a "context." It can be passed explicitly as arguments, but there are various other ways to manage it. For example, one popular design is to use a "Reader" monad, which essentially passes the state as an implicit argument to all functions that use the monad. Type classes such as `MonadDatabase` or `MonadLogger` may provide database and logging APIs utilizing the state made available by the Reader. Providing a meaningful minimal example is difficult because this type of abstraction is most beneficial in large applications, but here is a Reader example that is minimal for the points that I want to make: module Main (main) where -- https://hackage.haskell.org/package/base import Control.Monad.IO.Class (MonadIO(liftIO)) import Data.Bool (bool) import System.Environment (getArgs) -- https://hackage.haskell.org/package/transformers import Control.Monad.Trans.Reader (ReaderT(runReaderT), asks) data Locale = En | It class HasLocale a where getLocale :: a -> Locale instance HasLocale Locale where getLocale = id class MonadLocale m where askLocale :: m Locale instance (HasLocale r, Monad m) => MonadLocale (ReaderT r m) where askLocale = asks getLocale putLanguage :: (MonadIO m, MonadLocale m) => m () putLanguage = do locale <- askLocale liftIO . putStrLn $ case locale of En -> "English" It -> "Italiano" putHelloWorld :: (MonadIO m, MonadLocale m) => m () putHelloWorld = do locale <- askLocale liftIO . putStrLn $ case locale of En -> "Hello world!" It -> "Ciao mondo!" app :: (MonadIO m, MonadLocale m) => m () app = do putLanguage putHelloWorld main :: IO () main = do locale <- bool En It . elem "--it" <$> getArgs runReaderT app locale In this example, the state/context is simply a `Locale` value, which defaults to `En`. The `main` function checks if string `--it` is passed as an argument and configures the locale to `It` in that case. The final line runs the `app` function using a `ReaderT` monad transformer with the locale as the "environment." The `app` function, as well as all functions that it calls in the same monad, have access to this environment. Type class `HasLocale` just provides a `getLocale` function for getting a `Locale` value from some possibly larger value. The instance is the trivial case of `Locale` itself. Type class `MonadLocale` provides a locale API, just `askLocale` in this case. In a monad that implements `MonadLocale`, the `askLocale` function is able to get the locale. The instance provides a way to do this in a Reader monad that has an environment with a `HasLocale` instance. In this minimal example, the Reader environment is a `Locale` value, so that trivial `HasLocale` instance is used. The remaining three functions implement the example application. They do not specify a concrete monad; they instead specify constraints on the monad, allowing them to run in any monad that meets those constraints. The `MonadIO m` constraint is required to use `liftIO . putStrLn` in order to print to the screen, and the `MonadLocale m` constraint is required to get the configured locale. In this example, they are run in concrete monad `ReaderT Locale IO`, but note that they could also be run in different monads as long as the constraints are satisfied. The `app` function calls `putLanguage` and then `putHelloWorld`, and both of these functions are able to use `askLocale` to get the configured locale. $ minimal-context English Hello world! $ minimal-context --it Italiano Ciao mondo! The architecture/design of a project/program depends on the needs. In some programs, explicitly passing context as arguments is the best approach. In others, even `MonadIO` should be avoided, since `IO` makes anything possible. Getting back to your original question, the use of type classes allows a library author to implement functions that work across a wide variety of coding styles. Cheers, Travis On Sun, Feb 26, 2023 at 6:35 PM Pietro Grandinetti <pietro....@hotmail.it> wrote: > Hi Travis, > > Thanks. This was indeed helpful. I think I haven't grasped the concept of > "context" yet. Do you know any minimal example that shows this? > > Thanks. ------------------------------ Subject: Digest Footer _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners ------------------------------ End of Beginners Digest, Vol 169, Issue 7 *****************************************