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
******************************************

Reply via email to