<p>I just asked this question about Rust: <em><a href="https://www.reddit.com/r/rust/comments/14ttvlz/is_it_possible_to_create_a_default_trait/" rel="nofollow noreferrer">Is it possible to create a default trait implementation in Rust, and then override that trait implementation somewhere else?</a></em> My problem is, in my custom lang, I want to define a default implementation for printing error messages to the terminal. What I hate the most about JS/Node.js is the error message printing is terrible, so I would like to override all error messages and reformat it. Likewise in my language, I wanted to have the ability to override how error messages are displayed. And other things will use this pattern, but this is just top-of-mind.</p>
<p>The question is, how can I:</p>
<ol>
<li>Define the default implementation of stringifying?</li>
<li>Allow overriding (possibly multiple times) of the stringification?</li>
</ol>
<p>By multiple times, I mean a library might define some errors and renderings for them. Then another library might override that. Then an application might override that, so 3 layers of definitions, the last one which will take precedence (and all internal/external error messages will use that final formatter).</p>
<p>How can I do this in a statically typed sort of way? It appears Rust doesn't allow you to override trait implementations (for some reason I'm unaware of, waiting to hear about that!). Could you theoretically just add that feature to Rust without consequences? What about other languages, what is a good example how another language solves this problem?</p>
<p>In some ways it's kind of like dependency injection, but not 100% sure about that.</p>

<functions><traits><design-patterns>
Architecture for overriding "trait" implementations many times in different contexts?
CC BY-SA 4.0
2023-07-08T10:03:44.550Z
Is this similar to `alias_method` in Ruby? Could that be done in a statically typed sort of language somehow?
Lance Pollard
CC BY-SA 4.0
2023-07-08T12:19:04.407Z
Yes, what you're describing is basically solved by dependency injection. Scala has `given` as one answer already mentions, which are more exactly like the "overridden trait implementation" solution you describe, but it also has `implicit` variables, which allow actual dependency injection too. I guess these both solve the same problem in parallel ways? I don't know enough about Scala to answer for sure though.
pxeger
CC BY-SA 4.0
2023-08-10T14:57:48.550Z
Sooner or later you're going to want to "block overrides": override X with this Y, but don't let further code override Y. Somewhat like file permissions in NTFS.
Pablo H
<p>Scala uses the <code>given</code> system for a superset of what Rust traits do. For example, this Rust (pseudo-)code</p>
<pre class="lang-rust prettyprint-override"><code>trait Show {
  fn show(&amp;self) -&gt; String;
}

impl Show for String {
  fn show(&amp;self) -&gt; String {
    format!(&quot;\&quot;{}\&quot;&quot;, self)
  }
}

fn show(x: &amp;impl Show) {
  x.show()
}
</code></pre>
<p>converts to this Scala code:</p>
<pre class="lang-scala prettyprint-override"><code>trait Show[+A]:
  def show(a: A): String

given Show[String] where
  def show(str: String) = s&quot;\&quot;$str\&quot;&quot;

def show[A](a: A)(using sh: Show[A]) = sh(a)
</code></pre>
<p>The important difference is that givens act as variables - that is, they can be scoped.</p>
<pre class="lang-scala prettyprint-override"><code>def foo() =
  given Show[String] where
    def show(str: String) = s&quot;[${str.length}]$str&quot;
  println(show(&quot;hi&quot;))

println(show(&quot;hi&quot;)) // outputs &quot;hi&quot;
foo() // outputs [2]hi
</code></pre>
<p>Multiple libraries can export givens of the same type and you can choose which to use when you import them:</p>
<pre class="lang-scala prettyprint-override"><code>import lib.{given Show[String]}
println(show(&quot;hi&quot;)) // calls the library's implementation
</code></pre>
<p>And of course, you can mix the two things and use imports inside a block to override the default given</p>
<pre class="lang-scala prettyprint-override"><code>import bar.{given Show[String]}
def q() =
  import foo.{given Show[String]}
  println(show(&quot;hi&quot;))
println(show(&quot;hi&quot;))
q()
</code></pre>
<p>You can also decide to explicitly pass an instance to a function without having it as a <code>given</code>:</p>
<pre class="lang-scala prettyprint-override"><code>object A extends Show[String]:
  def show(str: String) = s&quot;$str from A&quot;
object B extends Show[String]:
  def show(str: String) = s&quot;$str from B&quot;
given Show[String] = A
println(show(&quot;hi&quot;)) // hi from A
println(show(&quot;hi&quot;)(using B)) // hi from B
</code></pre>
<p>All these features combined can make Scala <code>given</code>s much more powerful than Rust-style traits or traditional Haskell-like typeclasses, if used correctly.</p>

CC BY-SA 4.0
2023-07-08T06:10:25.520Z
2023-07-08T06:10:25.520Z
RubenVerg
CC BY-SA 4.0
2023-07-08T10:05:47.713Z
I don't see how this would allow overriding the calls to `show` that were done inside some external library already. How could this system allow me to change what `show` does in places it's already been called at in external libraries?
Lance Pollard
CC BY-SA 4.0
2023-07-08T14:45:56.673Z
@Lance sorry, didn't get that it was what your question is asking. If your library defines a given `Show[String]` and uses it internally - that is, doesn't expose it as an (optional) `using` parameter - I don't think there's a way to change that
RubenVerg
CC BY-SA 4.0
2023-07-08T16:02:25.373Z
@Lance If external library X has a function with signature `def foo[A: Show](argument: A)`, that's syntax sugar for `def foo[A](argument: A)(using showInstance: Show[A])`. And when that function calls `show`, it's really calling some method on that context object `showInstance`. That means that your calling library Y can invoke the function like `foo(whatever)` to get the "default" `Show` instance but can also invoke it as `foo(whatever)(using customShowImpl)` to force a custom one.
Silvio Mayolo
<h3>Your traits calls library code</h3>
<blockquote>
<p>By multiple times, I mean a library might define some errors and renderings for them. Then another library might override that. Then an application might override that, so 3 layers of definitions, the last one which will take precedence (and all internal/external error messages will use that final formatter).</p>
</blockquote>
<p>In existing languages, this level of configuration is possible if the default implementation is published in a public vtable, and default trait implementations calls into these vtables, that in turn are initially filled with the default implementation. Any library or user code can, then, change that. It's only a form of dependency <strong>pointer</strong> injection, as noted.</p>
<p><code>impl</code> in Rust, is more in direction of dependency <strong>code</strong> injection, in <code>comptime</code> no less. After the code is compiled, there is only functionality, no extension points.</p>
<h3>Aspect-oriented programming</h3>
<p>So if you want both, your language will need some form of <code>virtual trait</code> that accepts a default implementation, so that any library or user code can modify latter. If these 3 layers of (re)definitions are to occur at comptime, then your language will need some syntax to declare some <a href="https://en.wikipedia.org/wiki/Aspect-oriented_programming" rel="nofollow noreferrer">aspect</a> syntax rewriting rules.</p>
<p>You will note, in above Wikipedia link, that logging is a prime case in aspect-oriented programming.</p>

CC BY-SA 4.0
2023-07-08T16:25:38.767Z
2023-07-08T16:25:38.767Z
André L F S Bacci
# Architecture for overriding "trait" implementations many times in different contexts?
Posted by: username_0 on 2023-07-08
I just asked this question about Rust: *[Is it possible to create a default trait implementation in Rust, and then override that trait implementation somewhere else?](https://www.reddit.com/r/rust/comments/14ttvlz/is_it_possible_to_create_a_default_trait/)* My problem is, in my custom lang, I want to define a default implementation for printing error messages to the terminal. What I hate the most about JS/Node.js is the error message printing is terrible, so I would like to override all error messages and reformat it. Likewise in my language, I wanted to have the ability to override how error messages are displayed. And other things will use this pattern, but this is just top-of-mind.

The question is, how can I:

1. Define the default implementation of stringifying?
2. Allow overriding (possibly multiple times) of the stringification?

By multiple times, I mean a library might define some errors and renderings for them. Then another library might override that. Then an application might override that, so 3 layers of definitions, the last one which will take precedence (and all internal/external error messages will use that final formatter).

How can I do this in a statically typed sort of way? It appears Rust doesn't allow you to override trait implementations (for some reason I'm unaware of, waiting to hear about that!). Could you theoretically just add that feature to Rust without consequences? What about other languages, what is a good example how another language solves this problem?

In some ways it's kind of like dependency injection, but not 100% sure about that.
**Tags:** functions traits design-patterns
> **Comments:**
> **username_0**: Is this similar to `alias_method` in Ruby? Could that be done in a statically typed sort of language somehow?  
> **username_1**: Yes, what you're describing is basically solved by dependency injection. Scala has `given` as one answer already mentions, which are more exactly like the "overridden trait implementation" solution you describe, but it also has `implicit` variables, which allow actual dependency injection too. I guess these both solve the same problem in parallel ways? I don't know enough about Scala to answer for sure though.  
> **username_2**: Sooner or later you're going to want to "block overrides": override X with this Y, but don't let further code override Y. Somewhat like file permissions in NTFS.  
---
## 2 answers
### Answer by username_3 on 2023-07-08. Score: 5
Scala uses the given system for a superset of what Rust traits do. For example, this Rust (pseudo-)code
trait Show {
  fn show(&self) -> String;
}

impl Show for String {
  fn show(&self) -> String {
    format!("\"{}\"", self)
  }
}

fn show(x: &impl Show) {
  x.show()
}

converts to this Scala code:
trait Show[+A]:
  def show(a: A): String

given Show[String] where
  def show(str: String) = s"\"$str\""

def show[A](a: A)(using sh: Show[A]) = sh(a)

The important difference is that givens act as variables - that is, they can be scoped.
def foo() =
  given Show[String] where
    def show(str: String) = s"[${str.length}]$str"
  println(show("hi"))

println(show("hi")) // outputs "hi"
foo() // outputs [2]hi

Multiple libraries can export givens of the same type and you can choose which to use when you import them:
import lib.{given Show[String]}
println(show("hi")) // calls the library's implementation

And of course, you can mix the two things and use imports inside a block to override the default given
import bar.{given Show[String]}
def q() =
  import foo.{given Show[String]}
  println(show("hi"))
println(show("hi"))
q()

You can also decide to explicitly pass an instance to a function without having it as a given:
object A extends Show[String]:
  def show(str: String) = s"$str from A"
object B extends Show[String]:
  def show(str: String) = s"$str from B"
given Show[String] = A
println(show("hi")) // hi from A
println(show("hi")(using B)) // hi from B

All these features combined can make Scala givens much more powerful than Rust-style traits or traditional Haskell-like typeclasses, if used correctly.
> **Comments:**
> **username_0** (2023-07-08): I don't see how this would allow overriding the calls to `show` that were done inside some external library already. How could this system allow me to change what `show` does in places it's already been called at in external libraries?  
> **username_3** (2023-07-08): @Lance sorry, didn't get that it was what your question is asking. If your library defines a given `Show[String]` and uses it internally - that is, doesn't expose it as an (optional) `using` parameter - I don't think there's a way to change that  
> **username_4** (2023-07-08): @Lance If external library X has a function with signature `def foo[A: Show](argument: A)`, that's syntax sugar for `def foo[A](argument: A)(using showInstance: Show[A])`. And when that function calls `show`, it's really calling some method on that context object `showInstance`. That means that your calling library Y can invoke the function like `foo(whatever)` to get the "default" `Show` instance but can also invoke it as `foo(whatever)(using customShowImpl)` to force a custom one.  
---
### Answer by username_5 on 2023-07-08. Score: 2
### Your traits calls library code

> By multiple times, I mean a library might define some errors and renderings for them. Then another library might override that. Then an application might override that, so 3 layers of definitions, the last one which will take precedence (and all internal/external error messages will use that final formatter).

In existing languages, this level of configuration is possible if the default implementation is published in a public vtable, and default trait implementations calls into these vtables, that in turn are initially filled with the default implementation. Any library or user code can, then, change that. It's only a form of dependency **pointer** injection, as noted.

`impl` in Rust, is more in direction of dependency **code** injection, in `comptime` no less. After the code is compiled, there is only functionality, no extension points.

### Aspect-oriented programming

So if you want both, your language will need some form of `virtual trait` that accepts a default implementation, so that any library or user code can modify latter. If these 3 layers of (re)definitions are to occur at comptime, then your language will need some syntax to declare some [aspect](https://en.wikipedia.org/wiki/Aspect-oriented_programming) syntax rewriting rules.

You will note, in above Wikipedia link, that logging is a prime case in aspect-oriented programming.
---
