路径依赖类型的类似辅助模式?

时间:2018-02-14 01:16:15

标签: scala typeclass type-level-computation path-dependent-type

目标:我想写一下

$(function(){
  $('#password').on('keyup',function(){
    var $this =$(this),
        val=$this.val();
  var reg =/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{6,14}/
    console.log(reg.test(val))

  })
})


.red {
  color:red;
}

.green {
  color:green;
}
.grey-dot {
    background: #808080;
    width: 12px;
    height: 12px;
    float: left;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    -khtml-border-radius: 50%;
    border-radius: 50%;
    margin-right: 10px;
}

.green-dot {
    background: #77bc3f;
    width: 12px;
    height: 12px;
    float: left;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    -khtml-border-radius: 50%;
    border-radius: 50%;
    margin-right: 10px;
}

.red-dot {
    background: #fff;
    width: 10px;
    height: 10px;
    float: left;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    -khtml-border-radius: 50%;
    border-radius: 50%;
    margin-right: 10px;
    border: 1px solid #ff4848;
}

并具有与

相同的效果
feedImplicitInstance[Cat](new CatFood())`

我该怎么做? 是否可以这样做?

这是我尝试过的(但它没有真正起作用):

feedExplicitInstance(Cat.CatInstance)(new CatFood())

3 个答案:

答案 0 :(得分:1)

如果我们这样定义Aux

object AnimalTypeClass {
  type Aux[A, F] = AnimalTypeClass[A] { type FoodThatAnimalLikes = F }

  implicit object CatInstance extends AnimalTypeClass[Cat] {
    override type FoodThatAnimalLikes = CatFood
  }
}

然后我们可以通过一种方法召唤正确的隐式类型类:

def feed[A, F <: Food](f: F)(implicit animalTypeClass: AnimalTypeClass.Aux[A, F]) = {
  animalTypeClass.feed(f)
}

现在这个编译并运行:

feed(new CatFood())

我稍微更改了泛型类型参数的名称,但它们与示例中的大致相同。请注意隐式实例定义的更改。

答案 1 :(得分:1)

首先,将Aux放入AnimalTypeClass随播广告对象并切换其类型参数的顺序更为明智。虽然这些都不是必需来进行编译。

为了使您的首选调用约定feedImplicitInstance[Cat](new CatFood()) feedImplicitInstance被允许只有一个类型参数。但是Food必须是类型参数,因为不允许在参数列表中使用animal.FoodThatAnimalLikes等前向引用,因为您可能已经注意到了。这就是为什么你首先需要Aux的原因。要协调这些冲突的约束,您应该手动实现一种类型参数currying。这就是以下完整示例中Feeder类的用途:

object DepType extends App {

  def feedExplicitInstance[AnimalInstance]
      (animal: AnimalTypeClass[AnimalInstance])(food: animal.FoodThatAnimalLikes) = {
      animal.feed(food)
  }
  class Feeder[AnimalInstance] { 
    def apply[F <: Food](food: F)(implicit animal: AnimalTypeClass.Aux[AnimalInstance, F]) =
      animal.feed(food)
  }
  def feedImplicitInstance[AnimalInstance] = new Feeder[AnimalInstance]

  feedExplicitInstance(Cat.CatInstance)(new CatFood())
  feedImplicitInstance[Cat](new CatFood())

}

trait Food{
  def eat(): Unit
}
class CatFood extends Food{
  override def eat(): Unit = println("meow")
}

trait AnimalTypeClass[AnimalInstance] {
  type FoodThatAnimalLikes <: Food
  def feed(f: FoodThatAnimalLikes) = f.eat()
}
object AnimalTypeClass {
  type Aux[A, F <: Food]= AnimalTypeClass[A] {type FoodThatAnimalLikes = F}
}

trait Cat
object Cat {
  implicit object CatInstance extends AnimalTypeClass[Cat]{
    override type FoodThatAnimalLikes = CatFood
  }
}

答案 2 :(得分:0)

使用Yuval的答案,这就是我修改过的代码的样子:

object DepType2 extends App{

  println("bla")

  def feedExplicitInstance[AnimalInstance]
  (animal:AnimalTypeClass[AnimalInstance])(food:animal.FoodThatAnimalLikes) = {
    animal.feed(food)
  }

  def feedImplicitInstance[AnimalInstance,Food](food:Food)
                                               (implicit animal:AnimalTypeClass[AnimalInstance],aux:AnimalTypeClass.Aux[Food,AnimalInstance]) = {
    aux.feed(food)

  }
  feedExplicitInstance(AnimalTypeClass.CatInstance)(new CatFood())
  feedImplicitInstance(new CatFood())

}

trait Food{
  def eat():Unit
}

trait AnimalTypeClass [AnimalInstance] {
  type FoodThatAnimalLikes <: Food
  def feed(f:FoodThatAnimalLikes)=f.eat()
}

trait Cat

class CatFood extends Food{
  override def eat(): Unit = println("meow")
}

object AnimalTypeClass {
  type Aux[Food,Animal]= AnimalTypeClass[Animal] {type FoodThatAnimalLikes = Food}

  implicit object CatInstance extends AnimalTypeClass[Cat]{
    override type FoodThatAnimalLikes = CatFood
  }
}

所以我必须将animal中的aux更改为feedImplicitInstance,将object Cat更改为object AnimalTypeClass,现在一切正常。

当然,最初的问题有点棘手: 我怎么写feedImplicitInstance[Cat](new CatFood())

贾斯珀的答案是原始问题的答案。我还没有完全理解他的答案 - 我需要找一些时间仔细阅读,希望很快。