Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala';s类型系统和功能的输入n_Scala_Shapeless_Type Systems - Fatal编程技术网

Scala';s类型系统和功能的输入n

Scala';s类型系统和功能的输入n,scala,shapeless,type-systems,Scala,Shapeless,Type Systems,我想知道是否有办法修补Scala处理Function1和Function2..N中明显不一致的地方 对于函数1,例如Int=>String,参数列表(Int)与Int不相同(即使两者同构),但编译器会将输入推断为裸Int(参见下面的代码) 对于功能2..N,请说 val f:(字符串,Int)=>String=??? 编译器不会推断输入参数列表的任何类型。特别是,这里没有ParameterList[String,Int],即使它与(String,Int)元组和任何其他您喜欢放在String和In

我想知道是否有办法修补Scala处理Function1和Function2..N中明显不一致的地方

对于
函数1
,例如
Int=>String
,参数列表(Int)与Int不相同(即使两者同构),但编译器会将输入推断为裸Int(参见下面的代码)

对于
功能2..N
,请说 val f:(字符串,Int)=>String=??? 编译器不会推断输入参数列表的任何类型。特别是,这里没有ParameterList[String,Int],即使它与(String,Int)元组和任何其他您喜欢放在String和Int周围的包装器同构

我的第一个问题是,这是有原因的(或者这是scala TODO列表中存在的东西)?i、 e.为什么Function1可以解构为输入和输出类型,而不是Function2?有人想解决这个问题吗

有什么解决办法吗。具体地说,在下面的代码中,有没有一种方法可以使invoke2工作

package net.jtownson.swakka

import org.scalatest.FlatSpec
import org.scalatest.Matchers._
import shapeless.ops.function._
import shapeless.{HList, HNil, _}

class TypeclassOfFunctionTypeSpec extends FlatSpec {

  // Here, we know the return type of F is constrained to be O
  // (because that's how the shapeless FnToProduct typeclass works)
  def invoke1[F, I <: HList, O](f: F, i: I)
                               (implicit ftp: FnToProduct.Aux[F, I => O]): O = ftp(f)(i)

  // So let's try to express that by extracting the input type of F as FI
  def invoke2[FI, I <: HList, O](f: FI => O, i: I)
                                (implicit ftp: FnToProduct.Aux[FI => O, I => O]): O = ftp(f)(i)

  "Invoke" should "work for a Function1" in {

    // Here's our function (Int) => String
    val f: (Int) => String = (i) => s"I got $i"

    val l = 1 :: HNil

    // this works
    val r1: String = invoke1(f, l)

    // So does this. (With evidence that the compiler sees the function parameter list (Int) as just Int
    val r2: String = invoke2[Int, Int::HNil, String](f, l)

    r1 shouldBe "I got 1"
    r2 shouldBe "I got 1"
  }

  "Invoke" should "work for a Function2" in {

    // Here's our function (String, Int) => String
    val f: (String, Int) => String = (s, i) => s"I got $s and $i"

    val l = "s" :: 1 :: HNil

    // this works
    val r1: String = invoke1(f, l)

    // But this does not compile. There is no expansion for the type of FI
    // (String, Int) != the function Parameter list (String, Int)
    val r2: String = invoke2(f, l) 
    /*
    Error:(...) type mismatch;
    found   : (String, Int) => String
      required: ? => String
        val r1: String = invoke1(f, l)
    */

    r1 shouldBe "I got s and 1"
    r2 shouldBe "I got s and 1"
  }
}
package net.jtownson.swakka
导入org.scalatest.FlatSpec
导入org.scalatest.Matchers_
导入shapeless.ops.function_
导入无形状。{HList,HNil,}
类TypeclassOfFunctionTypeSpec扩展了FlatSpec{
//这里,我们知道F的返回类型被限制为O
//(因为这就是不成形的FnToProduct类型类的工作原理)
def invoke1[F,io]:O=ftp(F)(I)
//让我们试着通过将F的输入类型提取为FI来表示这一点
def invoke2[FI,io,I:I)
(隐式ftp:FnToProduct.Aux[FI=>O,I=>O]):O=ftp(f)(I)
中的“调用”应“适用于函数1”{
//这是我们的函数(Int)=>字符串
val f:(Int)=>String=(i)=>s“我得到了$i”
val l=1::HNil
//这很有效
val r1:String=invoke1(f,l)
//这也是如此。(有证据表明编译器将函数参数列表(Int)视为Int。)
val r2:String=invoke2[Int,Int::HNil,String](f,l)
r1应该是“我得到1”
r2应该是“我得到1”
}
中的“调用”应“适用于函数2”{
//这是我们的函数(String,Int)=>String
val f:(String,Int)=>String=(s,i)=>s“我得到了$s和$i”
val l=“s”::1::HNil
//这很有效
val r1:String=invoke1(f,l)
//但这不会编译。FI类型没有扩展
//(字符串,Int)!=函数参数列表(字符串,Int)
val r2:String=invoke2(f,l)
/*
错误:(…)类型不匹配;
找到:(字符串,Int)=>字符串
必需:?=>字符串
val r1:String=invoke1(f,l)
*/
r1应该是“我有s和1”
r2应该是“我有s和1”
}
}

Int=>String
Function1[Int,String]
(String,Int)=>String
Function2[String,Int,String]
((String,Int))=>String
Function1[(String,Int),String]
又称
Function1[Tuple2[String,Int],String]

如果定义隐式转换,则可以帮助Shapeless解析
FnToProduct
实例

implicit def tupledFnToProduct[FI1, FI2, O, Out0](implicit
  ftp: FnToProduct.Aux[Function2[FI1, FI2, O], Out0]
  ): FnToProduct.Aux[Function1[(FI1, FI2), O], Out0] =
  new FnToProduct[Function1[(FI1, FI2), O]] {
    override type Out = Out0
    override def apply(f: Function1[(FI1, FI2), O]) = ftp((x, y) => f(x, y))
  }
然后您可以使用
.tuple
调用
invoke2

val f: (String, Int) => String = (s, i) => s"I got $s and $i"

val l = "s" :: 1 :: HNil

val r2: String = invoke2(f.tupled, l)

r2 == "I got s and 1" //true

你知道
Function2#tuple
Function2#curried
方法吗?是的,我是:-),而且在Function1上不存在tuple。这可能是因为能够表达Function1的输入类型(作为裸类型)意味着不需要元组。可怜的老函数2..N缺少这一点。从这个意义上说,元组感觉像是一种解决方法。不过,我想知道的是,函数1和2在这方面存在差异有什么好的原因吗?