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: Tagged types (Markus Läll) 2. Re: Lifting over record syntax (Anthony Clayden) ---------------------------------------------------------------------- Message: 1 Date: Mon, 29 Oct 2018 19:42:14 +0100 From: Markus Läll <markus.l...@gmail.com> To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell <beginners@haskell.org> Subject: Re: [Haskell-beginners] Tagged types Message-ID: <caldaiubzjdycjgpuqwp-heq9pdhffhskmvqmq0i7t+tgnv+...@mail.gmail.com> Content-Type: text/plain; charset="utf-8" Hi Fredric, below are two ways to solve it, first with GADTs, the other with type classes. But I think in both cases you need to define the specific handling of the types in multiple places. With GADT's you need to add yet another constructor for yet another `t`. With type classes you need to specify the type in-line at the place you branch off, not sure how elegant that is. The singleton based approach is perhaps better than both of the below if your set of types is closed, since you only keep the string in one data constructor (in the `A "here"`), while with a GADT you have it nested in one of the AHdf5 or ACbf. On the other hand singletons need some extensions to be turned. Hope it helps, code follows: data A t = A String data Unchecked data Hdf5 data Cbf -- * A with GADT data A' where AHdf5 :: A Hdf5 -> A' ACbf :: A Cbf -> A' AUnchecked :: A Unchecked -> A' check :: A Unchecked -> A' check a = case a of A str | suffix ".h5" -> AHdf5 (A str) | suffix ".cdf" -> ACbf (A str) | otherwise -> AUnchecked (A str) where suffix suf = suf `isSuffixOf` str -- * Type classes type SomethnigCommon = () class Continue a where go :: A a -> SomethnigCommon instance Continue Hdf5 where go (A hdf5) = undefined -- implementation for hdf5 here instance Continue Cbf where go (A cbf) = undefined -- implementation for cbf here instance Continue Unchecked where go (A unchecked) = undefined -- implementation for unchecked here check' :: A Unchecked -> SomethnigCommon check' a = case a of A str | suffix ".h5" -> go (A str :: A Hdf5) | suffix ".cdf" -> go (A str :: A Cbf) | otherwise -> go (A str :: A Unchecked) where suffix suf = suf `isSuffixOf` str On Tue, Oct 2, 2018 at 6:48 PM PICCA Frederic-Emmanuel < frederic-emmanuel.pi...@synchrotron-soleil.fr> wrote: > Hello > > > suppose that I have a bunch of type like this > > data Unchecked > data Hdf5 > data Cbf > > data A t > A String > > The A thing come from a database as A Unchecked > > now if I read the String and it ends with .h5, I have a A Hdf5 type > and If the string end with .cbf, I have a A Cbf. > > So I would like a function which allow to return a A Hdf5 or a A Cbf > depending on the String content. > > check :: A Unchecked -> A ??? > check = ??? > > Is it possible to do this ? > > Thanks > > Frederic > > PS: At the end I will have more tha one tag. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -- Markus Läll -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20181029/fb2b0b01/attachment-0001.html> ------------------------------ Message: 2 Date: Tue, 30 Oct 2018 16:20:11 +1300 From: Anthony Clayden <anthony_clay...@clear.net.nz> To: beginners@haskell.org Subject: Re: [Haskell-beginners] Lifting over record syntax Message-ID: <cam7nrysveddfoonmvedns2npih-r1sezbxdnpzznmt0p_xo...@mail.gmail.com> Content-Type: text/plain; charset="utf-8" Hi Jaakko, oh dear you've picked on the most embarrassing part of Haskell. > data Person = Person {name::String, age::Int} deriving Show > > Now, I can create maybe-people like in applicative style: > > Person <$> Just "John Doe" <*> Nothing Hmm? That returns Nothing -- is that what you expect? Perhaps Person <$> Just "John Doe" <*> Just undefined But why not Just $ Person "John Doe" undefined > The problem with the [applicative] approach > is that it depends on the order of the arguments > because it doesn't utilize the record syntax. You'd think that a leading-edge language like Haskell would have really powerful record abstractions. With ways to avoid the shackles of argument ordering. Then it's sad to admit Haskell's records are feeble. Back in Haskell 98 people were saying "surely we can do better!" Well, essentially nothing's happened. So records are no more than pretty(-ish?) syntax for the ordered arguments style. The label names are not first-class. And field labels for building records only work in very restricted syntactic positions, as you point out: > I would like to get the benefits of the the record syntax > but with similar code simplicity as the applicative style has. > Do you have ideas is this possible? > My non-working pseudo-code would look like: > > Person <$> {name=Just "John Doe", age=Nothing} > > But this doesn't work, it's syntax error. You want that bit in braces to be a free-standing expression. That's called "anonymous/extensible records" (search Haskell wiki). "Anonymous" because it's not tied to any particular datatype. It's self-describing: I am a record with two fields labelled `name, age`; and the order of the labelled fields should be arbitrary. "Extensible" because you could start a record with just one labelled field, and extend it with another labelled field. But I'm not sure what the `Maybe` wrapping is doing for you? I'm going to ignore it. I have some good news and some bad news. There is a Haskell you can do n = (name = "John Doe") -- note round parens n_a = (age = undefined | n) -- | for extend the record p = Person n_a For that you need a slightly different data decl data Person = Person (Rec (name :: String, age :: Int)) deriving Show Round parens again; and a mysterious type constructor. But these records are first-class values. (They're a special variety of tuples.) Perhaps you don't need a datatype? type Person = Rec (name :: String, age :: Int) Then you don't need to apply a data constructor. This style of records is 'Trex' -- Typed Records with extensibility https://www.haskell.org/hugs/pages/hugsman/exts.html#sect7.2 The bad news: Trex is available only in a very old Haskell system, Hugs. So old that its download has bitrotted, see note here https://mail.haskell.org/pipermail/hugs-bugs/2018-July/001914.html GHC has had 12 years to come up with something comparable/better. So far, nothing. If you're wanting to get all Applicative and Functorial in GHC, there are heaps of record systems based around Lenses. http://hackage.haskell.org/package/lens-tutorial But that's going way beyond Beginners level; you'll need to call on Template Haskell; and probably add some plumbing of your own. (And under the hood you still have ordered arguments; they're rather better encapsulated.) AntC -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20181030/5da1edb8/attachment-0001.html> ------------------------------ Subject: Digest Footer _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners ------------------------------ End of Beginners Digest, Vol 124, Issue 15 ******************************************