2017-07-25 53 views
2

我的函数有1个参数,类型是字符串,但是长度是4,我可以在编译时验证这个参数吗?如何在编译时使用scala验证字符串格式

在haskell和F#中有类型级别,它可以在编译时进行验证,如nonEmptyList。

如何使它在scala中。我认为shapless可以做到这一点,但我不明白

感谢您提前建议

回答

3

是的,无形可以做到这一点。也许是这样的:

def f(s: Sized[IndexedSeq[Char], Nat._4]): ... 

虽然你不能直接传递字符串。你必须做类似f(Sized('a', 'b', 'c', 'd'))

0

你不能用香草斯卡拉。

,你可以去为这个创造的一种特殊类型,最好的方法 -

case class SpecialString(string: String) { 
    require(string.length == 4) 
    } 

然后,让你的函数接收SpecialString作为参数,而不是String

0

使用宏也是编译时验证的选项。看到这个帖子由Arnout恩格伦:http://blog.xebia.com/compile-time-evaluation-scala-macros/

我修改他的例子来定义字符串验证功能:

object CompileTimeStringCheck { 
    import scala.language.experimental.macros 

    // This function exposed to consumers has a normal Scala type: 
    def stringCheck(s: String): String = 
    // but it is implemented as a macro: 
    macro CompileTimeStringCheck.stringCheck_impl 

    import scala.reflect.macros.blackbox.Context 

    // The macro implementation will receive a 'Context' and 
    // the AST's of the parameters passed to it: 
    def stringCheck_impl(c: Context)(s: c.Expr[String]): c.Expr[String] = { 
    import c.universe._ 

    // We can pattern-match on the AST: 
    s match { 
     case Expr(Literal(Constant(nValue: String))) => 
     // We perform the calculation: 
     val result = normalStringCheck(nValue) 
     // And produce an AST for the result of the computation: 
     c.Expr(Literal(Constant(result))) 
     case other => 
     // Yes, this will be printed at compile time: 
     println("Yow!") 
     ??? 
    } 
    } 

    // The actual implementation is regular old-fashioned scala code:  
    private def normalStringCheck(s: String): String = 
    if (s.length == 4) return s 
    else throw new Exception("Baaaaaah!") 
} 

这里的渔获,但:这需要才能使用它来进行编译,即把它放入一个utils jar或其他东西。再次

import CompileTimeStringCheck._ 

object Test extends App { 
    println(stringCheck("yes!")) 
} 

,看到Arnout恩格伦的帖子更多细节和原溶液(http://blog.xebia.com/compile-time-evaluation-scala-macros/):然后你就可以在以后编译时使用它。

+0

非常感谢,但这是非常复杂的大声笑。 –