- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 Shapeless 的标记类型来获得良好的类型安全原语以通过我的业务逻辑。定义这些类型从一个简单的开始:
sealed trait MyTaggedStringTag
type MyTaggedString = String @@ MyTaggedStringTag
但是我为此添加了一些辅助逻辑,现在我的定义看起来更像:
sealed trait MyTaggedStringTag
type MyTaggedString = String @@ MyTaggedStringTag
object MyTaggedString {
def fromString(untaggedMyTaggedString: String): MyTaggedString = {
val myTaggedString = tag[MyTaggedStringTag](untaggedMyTaggedString)
myTaggedString
}
}
implicit class MyTaggedStringOps(val myTaggedString: MyTaggedString) extends AnyVal { def untagged = myTaggedString.asInstanceOf[String] }
因此,每个定义都有很多样板文件。我真的很想能够通过执行以下操作来生成它:
@tagged[String] type MyTaggedString
有没有办法用 Scala Meta 或其他代码生成工具来做这样的事情?
最佳答案
已更新
现在可以正常使用了,可以在我称之为 Taggy 的新库中看到.这是宏的最新版本:
class tagged extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
// Macro annotation type and value parameters come back as AST data, not
// values, and are accessed by destructuring `this`.
defn match {
case q"..$mods type $newType = ${underlyingType: Type.Name}" =>
TaggedImpl.expand(underlyingType, newType, mods)
case _ =>
abort("Correct usage: @tagged type NewType = UnderlyingType" )
}
}
}
object TaggedImpl {
def expand(underlyingType: Type.Name, newType: Type.Name, mods: Seq[Mod]) = {
// Shapeless needs a phantom type to join with the underlying type to
// create our tagged type. Ideally should never leak to external code.
val tag = Type.Name(newType.value + "Tag")
// The `fromX` helper will go in the companion object.
val companionObject = Term.Name(newType.value)
// We'll name the `fromX` method based on the underlying type.
val fromMethod = Term.Name("from" + underlyingType.value)
// The `untagged` helper goes in an implicit class, since the tagged type
// is only a type alias, and can't have real methods.
val opsClass = Type.Name(newType.value + "Ops")
q"""
sealed trait $tag
..$mods type $newType = com.acjay.taggy.tag.@@[$underlyingType, $tag]
..$mods object $companionObject {
def $fromMethod(untagged: $underlyingType): $newType = {
val tagged = com.acjay.taggy.tag[$tag](untagged)
tagged
}
}
..$mods implicit class $opsClass(val tagged: $newType) extends AnyVal {
def untagged = tagged.asInstanceOf[$underlyingType]
def modify(f: $underlyingType => $underlyingType) = $companionObject.$fromMethod(f(untagged))
}
"""
}
}
object tag {
def apply[U] = new Tagger[U]
trait Tagged[U]
type @@[+T, U] = T with Tagged[U]
class Tagger[U] {
def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U]
}
}
为了便于阅读,宏语法的解析和代码生成是分开的。您可以将 TaggedImpl.expand
内联到 meta
block 中。另请注意,此处的语法现在是 @tagged type MyTaggedString = String
。
原始答案
我把它作为概念证明工作。但它采用底层类型的字符串名称:
import scala.meta._
class tagged(_underlyingTypeName: String) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
// Can't figure out how to do this extraction as a quasiquote, so I
// figured out exactly the AST `this` produces to extract the string
// parameter.
val Term.New(
Template(
List(),
List(Term.Apply(Ctor.Ref.Name("tagged"), List(Lit.String(underlyingTypeName)))),
Term.Param(List(), Name.Anonymous(), None, None),
None
)
) = this
val q"..$mods type $tname[..$tparams]" = defn
val underlyingType = Type.Name(underlyingTypeName)
TaggedImpl.expand(tname, underlyingType)
}
}
object TaggedImpl {
def expand(taggedType: Type.Name, underlyingType: Type.Name) = {
val tag = Type.Name(taggedType.value + "Tag")
val companionObject = Term.Name(taggedType.value)
val fromMethodName = Term.Name("from" + underlyingType.value)
val opsClass = Type.Name(taggedType.value + "Ops")
q"""
sealed trait $tag
type $taggedType = shapeless.tag.@@[$underlyingType, $tag]
object $companionObject {
def $fromMethodName(untagged: $underlyingType): $taggedType = {
val tagged = shapeless.tag[$tag](untagged)
tagged
}
}
implicit class $opsClass(val tagged: $taggedType) extends AnyVal {
def untagged = tagged.asInstanceOf[$underlyingType]
}
"""
}
}
关于scala - 使用代码生成(如 Scala Meta)来抓取样板文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46005321/
我正在创建一个 SSO 服务器,以将所有用户集中在 ActiveDirectory(AD) 中并在那里管理他们,而不是每个特定应用程序的数据库。 为了制作这个服务器,我使用了 IdentityServ
几天前,我了解了 HTML5 样板文件,所以我还是个新手。我正在尝试使用样板进行试验,所以我继续下载了这个 boilerplate 但我对下载选项的差异感到困惑。 有一个用于下载现成的自定义文件的按钮
在Flutter中,我们需要为在dispose()中创建的许多内容写下State,例如 final _nameController = TextEditingController(); @ov
我正在开发一个更大的项目,我对空检查有点厌倦。我有一个 MongoDB 实体(文档),该实体引用了另一个文档。几乎在每种情况下,我都会检查它是否为空,如果不是则执行某些操作。我知道 Java 8 中有
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
每次我向项目中添加新表单时,它都会在 use 子句中删除一大堆样板文件。 uses Windows, Messages, SysUtils, Variants, Classes, Graphics
这是我的Todo应用程序的基本结构,看起来像是“main.go”; package main import ( "encoding/json" "fmt" "log"
我有一个实现接口(interface)的类。还有另一个类也实现了这个接口(interface),并且第二个类的实例支持我的类的实现。 对于接口(interface)指定的许多方法,我的类只是将它们直接
每次我想要一个 SeekBar 和一个相应的 TextView 来显示它的数值时,为了减少代码的编写,我编写了以下抽象类: abstract public class SeekBarWrapper {
我正在考虑使用 CSS 样板(kube 或任何其他)来构建我的表单。它们在示例 html 文件中工作得很好,但是如果我想在不受控制的环境中使用(意味着 css 不在我的控制范围内),它会弄乱这些样式。
我很难在 CSS 中显示我的背景图片。我创建了一个带有 .top 类的 div,但每次我使用 background-image css 属性时,除了颜色、高度和宽度外什么都没有显示。我还使用 Init
尝试使用yarn导入react-image-crop包并将其添加到react样板中。 安装包后出现此错误 Module parse failed: /Users/...../frontend/node
我正在使用 skeleton 构建网站框架,使用 a fork that compiles from LESS . 在不丢失骨架提供的底层脚手架的情况下自定义样式的正确方法是什么?我知道我可以更改变量
从开箱即用的 HTML5 样板安装中,我使用以下代码 body { background-image:url('img/bg.png'); background-repeat:repeat-y; }
我正在使用 GWT 事件和地点框架来构建我的应用程序,结果很好。让我烦恼的一件事是 ActivityMapper实现是 (1) 接收应用程序中的所有 View (2) 包含一个巨大的 if/else
我正在使用generator-babel-boilerplate然后运行npm run test-browser。这可以正常工作,但我需要在浏览器中测试一些内容,并且我不确定如何查看正在提供的内容。
我经常使用以下样板,并希望将其消除。它看起来像这样: type Configured = ReaderT Config doSomething :: Configured IO Data doSome
我正在使用 ASP.NET 样板。我有一个 Angular 应用程序(ABP 外部),我想使用我的 API。 为此,我通过 /api/TokenAuth/Authenticate 获取访问 token
我的 JS 为: (function () { var controllerId = 'app.views.dashboard'; angular.module('app').cont
我们曾经可以输入 !在 vscode 中的 html 文档中获取 html boiler plate content completion as documented here . 然而它不再起作用。
我是一名优秀的程序员,十分优秀!