How can I define an HKT for instance (over object) methods in Scala?Difference between object and class in ScalaScala immutable objects and traits with val fieldsScala mixin to class instanceWhen to use val or def in Scala traits?Define custom HashSet in Scala?Defining variables in scala using defScala: Object inherits on runtimeWhy Scala case class copy method parameterised only with the variables defined in the case class?Is there a way to “program to interface” in scalaWhat is the use of Universal trait in Scala?
How similar (or not) are recorder, fife, and flute fingerings?
Can a Tiefling be born from two human parents?
Water Jug Problem in AI
What is each symbol in a octal number called as?
Heavy condensation inside car during winter. Tried multiple things, but no results!
Command error occurred
What's the difference between words "tongue" and "lingua"?
Intersection of four circles
Is there a coup going on in Bolivia?
Conflict between a religious belief that accounts for the existence of transgender people vs. one that doesn't
Does a small cup of coffee result in a 45% reduced blood flow to the brain?
Phrase/Word-pair for a variant of master-slave relationship
20 cards with no Set
What is the last point where one can throw away fruits if one has indicated "not bringing any fruit" on the US customs form when flying to the US?
Why is hydro-electric power still scarce in some places?
Can the jeopardy of being judged be fought against in court?
Size Does Matter (at least referring to bottles)
In Flanders Fields
Did any astronauts on a mission complain about waking up?
What is the relationship between taxes and annual liquidation of the markets?
Why were some early PC 3D cards unsuitable for 2D graphics?
A novel about "helpful" woodlice aliens who eventually end up destroying every civilization they try to help
Simple run-length encoding decoder
Is there a bulletproof way to know a file has been successfully decrypted?
How can I define an HKT for instance (over object) methods in Scala?
Difference between object and class in ScalaScala immutable objects and traits with val fieldsScala mixin to class instanceWhen to use val or def in Scala traits?Define custom HashSet in Scala?Defining variables in scala using defScala: Object inherits on runtimeWhy Scala case class copy method parameterised only with the variables defined in the case class?Is there a way to “program to interface” in scalaWhat is the use of Universal trait in Scala?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
How do you define an HKT in Scala to provide methods, such as map
, as methods on instances instead of functions on objects?
I know you can
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
object Q extends M[Q]
def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
class Q[A](val e: A)
Q.map(new Q(1))(_.toDouble)
However, I want to use map
on instances instead. I haven't seen any literature that does this, so I've written the following.
trait M[A, F[A]]
def map[B](f: A => B): F[B]
class Q[A](val e: A) extends M[A, Q]
def map[B](f: A => B) = new Q(f(e))
new Q(1).map(_.toDouble)
Is it idiomatic Scala? Does it do what map
should do? Are there limitations compared with the object version above? (An aside, with extends M[A, Q[A]]
it won't compile - why?)
I have seen
trait M[A]
def map[B](f: A => B): M[B]
but then Q
's map
could return a class R[A] extends M[A]
which isn't desired.
scala monads traits higher-kinded-types
add a comment
|
How do you define an HKT in Scala to provide methods, such as map
, as methods on instances instead of functions on objects?
I know you can
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
object Q extends M[Q]
def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
class Q[A](val e: A)
Q.map(new Q(1))(_.toDouble)
However, I want to use map
on instances instead. I haven't seen any literature that does this, so I've written the following.
trait M[A, F[A]]
def map[B](f: A => B): F[B]
class Q[A](val e: A) extends M[A, Q]
def map[B](f: A => B) = new Q(f(e))
new Q(1).map(_.toDouble)
Is it idiomatic Scala? Does it do what map
should do? Are there limitations compared with the object version above? (An aside, with extends M[A, Q[A]]
it won't compile - why?)
I have seen
trait M[A]
def map[B](f: A => B): M[B]
but then Q
's map
could return a class R[A] extends M[A]
which isn't desired.
scala monads traits higher-kinded-types
1
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship isQ _has_ an instance of M
instead ofQ _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicitOps
orSyntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.
– Luis Miguel Mejía Suárez
Mar 28 at 22:54
add a comment
|
How do you define an HKT in Scala to provide methods, such as map
, as methods on instances instead of functions on objects?
I know you can
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
object Q extends M[Q]
def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
class Q[A](val e: A)
Q.map(new Q(1))(_.toDouble)
However, I want to use map
on instances instead. I haven't seen any literature that does this, so I've written the following.
trait M[A, F[A]]
def map[B](f: A => B): F[B]
class Q[A](val e: A) extends M[A, Q]
def map[B](f: A => B) = new Q(f(e))
new Q(1).map(_.toDouble)
Is it idiomatic Scala? Does it do what map
should do? Are there limitations compared with the object version above? (An aside, with extends M[A, Q[A]]
it won't compile - why?)
I have seen
trait M[A]
def map[B](f: A => B): M[B]
but then Q
's map
could return a class R[A] extends M[A]
which isn't desired.
scala monads traits higher-kinded-types
How do you define an HKT in Scala to provide methods, such as map
, as methods on instances instead of functions on objects?
I know you can
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
object Q extends M[Q]
def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
class Q[A](val e: A)
Q.map(new Q(1))(_.toDouble)
However, I want to use map
on instances instead. I haven't seen any literature that does this, so I've written the following.
trait M[A, F[A]]
def map[B](f: A => B): F[B]
class Q[A](val e: A) extends M[A, Q]
def map[B](f: A => B) = new Q(f(e))
new Q(1).map(_.toDouble)
Is it idiomatic Scala? Does it do what map
should do? Are there limitations compared with the object version above? (An aside, with extends M[A, Q[A]]
it won't compile - why?)
I have seen
trait M[A]
def map[B](f: A => B): M[B]
but then Q
's map
could return a class R[A] extends M[A]
which isn't desired.
scala monads traits higher-kinded-types
scala monads traits higher-kinded-types
edited Mar 28 at 22:12
Joel Berkeley
asked Mar 28 at 21:47
Joel BerkeleyJoel Berkeley
1,6628 silver badges24 bronze badges
1,6628 silver badges24 bronze badges
1
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship isQ _has_ an instance of M
instead ofQ _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicitOps
orSyntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.
– Luis Miguel Mejía Suárez
Mar 28 at 22:54
add a comment
|
1
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship isQ _has_ an instance of M
instead ofQ _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicitOps
orSyntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.
– Luis Miguel Mejía Suárez
Mar 28 at 22:54
1
1
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship is
Q _has_ an instance of M
instead of Q _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicit Ops
or Syntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.– Luis Miguel Mejía Suárez
Mar 28 at 22:54
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship is
Q _has_ an instance of M
instead of Q _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicit Ops
or Syntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.– Luis Miguel Mejía Suárez
Mar 28 at 22:54
add a comment
|
1 Answer
1
active
oldest
votes
There's a library specifically for this: https://github.com/mpilquist/simulacrum
You can also do it yourself. The typical pattern is to define a corresponding implicit MOps
class or whatever:
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
implicit class MOps[F[_] : M, A](x: F[A])
def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
Then example usage:
case class Box[A](a: A)
implicit val BoxM = new M[Box]
def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
Box(2).map(_.toString)
But it's a lot of boilerplate, so simulacrum does it all for you (and more).
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
Your approach allows for some weird things likeclass Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html
– Joe K
Mar 28 at 22:56
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid'sempty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way
– Joe K
Mar 28 at 22:58
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55407322%2fhow-can-i-define-an-hkt-for-instance-over-object-methods-in-scala%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
There's a library specifically for this: https://github.com/mpilquist/simulacrum
You can also do it yourself. The typical pattern is to define a corresponding implicit MOps
class or whatever:
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
implicit class MOps[F[_] : M, A](x: F[A])
def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
Then example usage:
case class Box[A](a: A)
implicit val BoxM = new M[Box]
def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
Box(2).map(_.toString)
But it's a lot of boilerplate, so simulacrum does it all for you (and more).
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
Your approach allows for some weird things likeclass Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html
– Joe K
Mar 28 at 22:56
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid'sempty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way
– Joe K
Mar 28 at 22:58
add a comment
|
There's a library specifically for this: https://github.com/mpilquist/simulacrum
You can also do it yourself. The typical pattern is to define a corresponding implicit MOps
class or whatever:
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
implicit class MOps[F[_] : M, A](x: F[A])
def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
Then example usage:
case class Box[A](a: A)
implicit val BoxM = new M[Box]
def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
Box(2).map(_.toString)
But it's a lot of boilerplate, so simulacrum does it all for you (and more).
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
Your approach allows for some weird things likeclass Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html
– Joe K
Mar 28 at 22:56
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid'sempty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way
– Joe K
Mar 28 at 22:58
add a comment
|
There's a library specifically for this: https://github.com/mpilquist/simulacrum
You can also do it yourself. The typical pattern is to define a corresponding implicit MOps
class or whatever:
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
implicit class MOps[F[_] : M, A](x: F[A])
def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
Then example usage:
case class Box[A](a: A)
implicit val BoxM = new M[Box]
def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
Box(2).map(_.toString)
But it's a lot of boilerplate, so simulacrum does it all for you (and more).
There's a library specifically for this: https://github.com/mpilquist/simulacrum
You can also do it yourself. The typical pattern is to define a corresponding implicit MOps
class or whatever:
trait M[F[_]]
def map[A, B](f: F[A])(fn: A => B): F[B]
implicit class MOps[F[_] : M, A](x: F[A])
def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
Then example usage:
case class Box[A](a: A)
implicit val BoxM = new M[Box]
def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
Box(2).map(_.toString)
But it's a lot of boilerplate, so simulacrum does it all for you (and more).
edited Mar 28 at 23:09
answered Mar 28 at 22:22
Joe KJoe K
15.8k1 gold badge26 silver badges47 bronze badges
15.8k1 gold badge26 silver badges47 bronze badges
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
Your approach allows for some weird things likeclass Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html
– Joe K
Mar 28 at 22:56
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid'sempty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way
– Joe K
Mar 28 at 22:58
add a comment
|
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
Your approach allows for some weird things likeclass Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html
– Joe K
Mar 28 at 22:56
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid'sempty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way
– Joe K
Mar 28 at 22:58
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
so you define the map as per the object version then use implicits to give that functionality to the instance?
– Joel Berkeley
Mar 28 at 22:33
1
1
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
what implications are there for this approach compared to mine?
– Joel Berkeley
Mar 28 at 22:52
1
1
Your approach allows for some weird things like
class Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html– Joe K
Mar 28 at 22:56
Your approach allows for some weird things like
class Foo[A] extends M[A, Bar]
. This is a common problem, I think this is the best write-up I've seen about it: tpolecat.github.io/2015/04/29/f-bounds.html– Joe K
Mar 28 at 22:56
1
1
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid's
empty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way– Joe K
Mar 28 at 22:58
Also, some methods of some typeclasses don't have instances associated with them, e.g. Monoid's
empty
method. So these typeclasses have to use this style of representation, and once you start having a few of this form, you often want inheritance (Monoid[A] extends Semigroup[A]
) and pretty soon it's easier to do everything this way– Joe K
Mar 28 at 22:58
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55407322%2fhow-can-i-define-an-hkt-for-instance-over-object-methods-in-scala%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
So, you want a typeclass. The idea is that there is only one instance of the typeclass for your type, because here the relation ship is
Q _has_ an instance of M
instead ofQ _is_ an instance of M
. Usually, in Scala, those instances are made implicit, so you can use them without having to pass them manually. Additionally, one usually defines an implicitOps
orSyntax
class (like Joe K did) to provide the functions of the typeclass with a regular method notation, just to make their use more natural.– Luis Miguel Mejía Suárez
Mar 28 at 22:54