A type of secure method join that does not allow repetition of operations

I want to implement a chain of methods, as in these issues:

Best practice for implementing a Scala tag that supports a chain of methods ;

Scala DSL: a chain of methods with parameterless methods

However, I want that after using the “property” it can no longer be used. For example, suppose I have a class “Myclass” for which I want to allow the definition of “foo” and “bar” to be defined no more than once, and I don’t need the final return type. In this way:

val c = new Myclass c foo //ok ! c foo bar // ok! c foo foo // refuse to compile c foo bar foo //refuse to compile 

I have been struggling with this problem for a while, and my vision starts to become blurry! I tried to use implicit classes, however, whether they need to parse objects that did not use the related property, and I cannot find how they should "consume" the property by removing it from the property of the object, and, again, I cannot find, as.

I'm currently looking in the reflection API, but for me it's still a bit unclear.

Help will be appreciated! =)

+6
source share
2 answers

See Phantom Types in Haskell and Scala by James Irie .

You can also use a line type template:

 trait TTrue trait TFalse @annotation.implicitNotFound(msg = "Cannot call same method twice.") sealed abstract class =^=[From, To] object =^= { private val singleton_=^= = new =^=[Any, Any]{} implicit def tpEquals[A]: A =^= A = singleton_=^=.asInstanceOf[A =^= A] } class Myclass[TFoo, TBar, TBuz] private(){ def foo(implicit e: TFoo =^= TFalse) = new Myclass[TTrue, TBar, TBuz] def bar(implicit e: TBar =^= TFalse) = new Myclass[TFoo, TTrue, TBuz] def buz(implicit e: TBuz =^= TFalse) = new Myclass[TFoo, TBar, TTrue] } object Myclass{ def apply() = new Myclass[TFalse, TFalse, TFalse] } 

to be used in this way

 scala> Myclass().foo.bar.buz res0: Myclass[TTrue,TTrue,TTrue] = Myclass@12ac706a scala> Myclass().bar.buz.foo res1: Myclass[TTrue,TTrue,TTrue] = Myclass@1e69dff6 scala> Myclass().foo.buz.foo <console>:12: error: Cannot call same method twice. Myclass().foo.buz.foo ^ 
+14
source

here you can ifnd an improved solution:

http://jim-mcbeath.blogspot.fr/2009/09/type-safe-builder-in-scala-part-3.html

(which actually relies on phantom types)

0
source

Source: https://habr.com/ru/post/950359/


All Articles