Identity operator for types

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Identity operator for types

Juan Miguel Vilar
Hi, Café:

I am not sure how to make the question, but the idea is to have a type
operator that returns the same type. Let me show what I need. I have
some type like this:

data Example f t = Example (f t)

So if I want a type variable that contains a list of integers, I can use
Example [] Int and then treat the content like a list:

f :: Example [] Int -> Int
f (Example l) = length l

Now, the problem is what can I do to have a type that contains a
single Int? Is there a sort of id for types so that I can write

f :: Example ?? Int -> Int
f (Example i) = 2 * i
?

Thanks in advance

Juan Miguel Vilar

--
Juan Miguel Vilar Torres
Profesor titular de universidad
Departamento de Lenguajes y Sistemas Informáticos
Escuela Superior de Tecnología y Ciencias Experimentales
Universitat Jaume I
Av. de Vicent Sos Baynat s/n
12071 Castelló de la Plana (Spain)
Tel: +34 964 72 8365
Fax: +34 964 72 8435
[hidden email]
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

ALeX Kazik
Hi Juan,

> Now, the problem is what can I do to have a type that contains a
> single Int? Is there a sort of id for types so that I can write

Identity is the solution

f :: Example Identity Int -> Int
f (Example i) = 2 * runIdentity i

Alex.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

Juan Miguel Vilar
El 17/5/19 a las 11:56, ALeX Kazik escribió:

> Hi Juan,
>
>> Now, the problem is what can I do to have a type that contains a
>> single Int? Is there a sort of id for types so that I can write
>
> Identity is the solution
>
> f :: Example Identity Int -> Int
> f (Example i) = 2 * runIdentity i
>
> Alex.
>
Thank you Alex, but this forces the use of runIdentity. I am aware that
Identity Int and Int are isomorphic, but my problem is more aesthetic, I
would like that the f t was t. I want to use it in a library and I don't
want the users to be aware of details that should be irrelevant.
Sometimes they will use lists, sometimes simple times, and would like
that to be as transparent as possible.

Juan Miguel

--
Juan Miguel Vilar Torres
Profesor titular de universidad
Departamento de Lenguajes y Sistemas Informáticos
Escuela Superior de Tecnología y Ciencias Experimentales
Universitat Jaume I
Av. de Vicent Sos Baynat s/n
12071 Castelló de la Plana (Spain)
Tel: +34 964 72 8365
Fax: +34 964 72 8435
[hidden email]
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

Ben Franksen
Am 17.05.19 um 12:33 schrieb Juan Miguel Vilar:

> El 17/5/19 a las 11:56, ALeX Kazik escribió:
>>> Now, the problem is what can I do to have a type that contains a
>>> single Int? Is there a sort of id for types so that I can write
>>
>> Identity is the solution
>>
>> f :: Example Identity Int -> Int
>> f (Example i) = 2 * runIdentity i
>>
> Thank you Alex, but this forces the use of runIdentity. I am aware that
> Identity Int and Int are isomorphic, but my problem is more aesthetic, I
> would like that the f t was t. I want to use it in a library and I don't
> want the users to be aware of details that should be irrelevant.
> Sometimes they will use lists, sometimes simple times, and would like
> that to be as transparent as possible.

https://reasonablypolymorphic.com/blog/higher-kinded-data/ shows how to
do that using closed type families.

Cheers
Ben

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

Jack Kelly
In reply to this post by Juan Miguel Vilar
Juan Miguel Vilar <[hidden email]> writes:

> El 17/5/19 a las 11:56, ALeX Kazik escribió:
>>> Now, the problem is what can I do to have a type that contains a
>>> single Int? Is there a sort of id for types so that I can write
>>
>> Identity is the solution
>>
> Thank you Alex, but this forces the use of runIdentity. [...]
> Sometimes they will use lists, sometimes simple times, and would like
> that to be as transparent as possible.

I do not like the sibling thread's suggestion of using closed type
families, because I think the regulatity of always having the `f t`
present is a nicer aesthetic. Using a type family to unwrap the
`Identity` makes it noisier to write functions that consume your
structure and are polymorphic in `f`.

You can alleviate some of the syntactic noise of `runIdentity` with
careful choices of type aliases or other helper functions. The type
aliases (and `runFoo` functions) for monad transformers are good
examples, and the `(==>)` function in dependent-sum[1] is a good
additional example of the latter. To save you the click, DSum in
dependent-sum is defined like this:

    data DSum tag f where
      !(tag a) :=> f a

The (==>) helper is defined like this:

    (==>) :: Applicative f => tag a -> a -> DSum tag f
    tag ==> a = tag :=> f a

So when f ~ Identity (or any other Applicative), the machinery becomes
that much easier to use.

-- Jack

[1]: https://hackage.haskell.org/package/dependent-sum-0.5/docs/Data-Dependent-Sum.html
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

Juan Miguel Vilar
El 17/5/19 a las 13:01, Jack Kelly escribió:

> Juan Miguel Vilar <[hidden email]> writes:
>
>> El 17/5/19 a las 11:56, ALeX Kazik escribió:
>>>> Now, the problem is what can I do to have a type that contains a
>>>> single Int? Is there a sort of id for types so that I can write
>>>
>>> Identity is the solution
>>>
>> Thank you Alex, but this forces the use of runIdentity. [...]
>> Sometimes they will use lists, sometimes simple times, and would like
>> that to be as transparent as possible.
>
> I do not like the sibling thread's suggestion of using closed type
> families, because I think the regulatity of always having the `f t`
> present is a nicer aesthetic. Using a type family to unwrap the
> `Identity` makes it noisier to write functions that consume your
> structure and are polymorphic in `f`.
>
> You can alleviate some of the syntactic noise of `runIdentity` with
> careful choices of type aliases or other helper functions. The type
> aliases (and `runFoo` functions) for monad transformers are good
> examples, and the `(==>)` function in dependent-sum[1] is a good
> additional example of the latter. To save you the click, DSum in
> dependent-sum is defined like this:
>
>      data DSum tag f where
>        !(tag a) :=> f a
>
> The (==>) helper is defined like this:
>
>      (==>) :: Applicative f => tag a -> a -> DSum tag f
>      tag ==> a = tag :=> f a
>
> So when f ~ Identity (or any other Applicative), the machinery becomes
> that much easier to use.
>
> -- Jack
>
> [1]: https://hackage.haskell.org/package/dependent-sum-0.5/docs/Data-Dependent-Sum.html
>

Thank you, Jack:

I can't see the sibling thread you mentioned. On the other hand, as I
said it is sort of an aesthetic question, so I think I can live with
Identity.

   Juan Miguel

--
Juan Miguel Vilar Torres
Profesor titular de universidad
Departamento de Lenguajes y Sistemas Informáticos
Escuela Superior de Tecnología y Ciencias Experimentales
Universitat Jaume I
Av. de Vicent Sos Baynat s/n
12071 Castelló de la Plana (Spain)
Tel: +34 964 72 8365
Fax: +34 964 72 8435
[hidden email]
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Identity operator for types

Jack Kelly
Juan Miguel Vilar <[hidden email]> writes:

> El 17/5/19 a las 13:01, Jack Kelly escribió:
>
>> I do not like the sibling thread's suggestion of using closed type
>> families...
>
> I can't see the sibling thread you mentioned. On the other hand, as I
> said it is sort of an aesthetic question, so I think I can live with
> Identity.

Oh. In that case, here is the blog post they discussed, with the
approach that I personally dislike:

https://reasonablypolymorphic.com/blog/higher-kinded-data/

The key part is the HKD type family:

    {-# LANGUAGE TypeFamilies #-}

    -- "Higher-Kinded Data"
    type family HKD f a where
      HKD Identity a = a
      HKD f        a = f a

    data Person' f = Person
      { pName :: HKD f String
      , pAge  :: HKD f Int
      } deriving (Generic)

HTH,

-- Jack
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.