編集:私は質問をより説明的に更新しました。有効なマクロ内のモナドの値へのスカラーの暗黙的な変換
メモ:私はScala 2.11コンパイラを使用しています。これは、LMSチュートリアルプロジェクトで使用されているコンパイラのバージョンです。
私はHaskellで書かれたDSLをScalaに移植しています。 DSLは命令的言語なので、私はdo-notationを持つモナド、すなわちWriterT [Stmt] (State Label) a
を使用しました。これをScalaに移植するのに問題がありましたが、ReaderWriterState
モナドを使用し、Reader
コンポーネントのUnitを使用することで問題を回避できました。私はその後、ハスケルにあるdo-notationの代替案を探しました。 For-comprehensionsはScalaのこの代替案であると考えられていますが、それらはシーケンスに合わせて調整されています。タプルにパターンが一致しない場合、filter
への呼び出しが挿入されます。だから私は選択肢を探し始め、複数のライブラリが見つかりました:effectful
、monadless
、およびeach
です。私はeffectful
を最初に試してみましたが、私は達成したいと思っていました。さらに、Haskellのdo-notationよりも好きで、ScalaZ
のReaderWriterState
モナドでうまくいきました。私のDSLには、Drop()
(ケースクラス)のようなアクションがあり、ステートメントとして直接使用できるようにしたいと考えています。私はこのために暗黙を使用することを望んだが、(そのことについては同等またはmonadless
)effectful
の!
方法が一般的すぎるので、私はScalaは自動的にタイプStmt
(Unit
を返すReaderWriterState
)の何かに私のAction
ケースクラスを変換することができません。
したがって、暗黙でない場合、それを達成する別の方法がありますか?
Main.passes2
に示されているように、私は使用しても構わない回避策を見つけましたが、私が遭遇した言語の制限があるのか、単にScalaの経験が足りないのか不思議です。
Main.fails1
次のエラーメッセージが表示されます。Implicit not found:scalaz.Unapply[scalaz.Monad, question.Label]
。型を種類クラスscalaz.Monad
で分類されたタイプM[_]
のatypeコンストラクタに適用解除することができません。タイプクラスがimplicitly[scalaz.Monad[type constructor]]
をコンパイルして定義されていることを確認し、オブジェクトタイプUnapply
の内容を確認します。これは一般的なタイプの「形状」のみをカバーします。 ScalaZからそのUnapply
来る
そしてMain.fails2
と私は取得します:値!
は、私はそれが欠けている暗黙的な定義を書くだけの問題であると仮定しquestion.Label
のメンバーではありません、 Scalaが私に書いてほしいと思っていることは確かではありません。
私のビルドの最も重要なビット。
scalaVersion := "2.11.2",
と依存関係:SBTバージョンです。ここ
libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.11.2",
libraryDependencies += "org.scala-lang" % "scala-library" % "2.11.2",
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.2",
libraryDependencies += "org.pelotom" %% "effectful" % "1.0.1",
は、私が試したものとそれらのものを実行するために必要なコードを含む、関連するコードです:
package question
import scalaz._
import Scalaz._
import effectful._
object DSL {
type GotoLabel = Int
type Expr[A] = ReaderWriterState[Unit, List[Action], GotoLabel, A]
type Stmt = Expr[Unit]
def runStmt(stmt: Stmt, startLabel: GotoLabel): (Action, GotoLabel) = {
val (actions, _, updatedLabel) = stmt.run(Unit, startLabel)
val action = actions match {
case List(action) => action
case _ => Seq(actions)
}
(action, updatedLabel)
}
def runStmt(stmt: Stmt): Action = runStmt(stmt, 0)._1
def getLabel(): Expr[GotoLabel] =
ReaderWriterState((_, label) => (Nil, label, label))
def setLabel(label: GotoLabel): Stmt =
ReaderWriterState((_, _) => (Nil, Unit, label))
implicit def actionStmt(action: Action): Stmt =
ReaderWriterState((_, label) => (List(action), Unit, label))
}
import DSL._
final case class Label(label: String) extends Action
final case class Goto(label: String) extends Action
final case class Seq(seq: List[Action]) extends Action
sealed trait Action {
def stmt(): Stmt = this
}
object Main {
def freshLabel(): Expr[String] = effectfully {
val label = getLabel.! + 1
setLabel(label).!
s"ants-$label"
}
def passes0() =
freshLabel()
.flatMap(before => Label(before))
.flatMap(_ => freshLabel())
.flatMap(after => Label(after));
def passes1() = effectfully {
unwrap(actionStmt(Label(unwrap(freshLabel()))))
unwrap(actionStmt(Label(unwrap(freshLabel()))))
}
def fails1() = effectfully {
unwrap(Label(unwrap(freshLabel())))
unwrap(Label(unwrap(freshLabel())))
}
def pasess2() = effectfully {
Label(freshLabel.!).stmt.!
Label(freshLabel.!).stmt.!
}
def fails2() = effectfully {
Label(freshLabel.!).!
Label(freshLabel.!).!
}
def main(args: Array[String]): Unit = {
runStmt(passes0())
}
}
私は、あなたが不平を言うことを正確に行おうと努力したという事実を考慮して、質問の質に関する最初のコメントをかなり不公平にしています。コードサイズを制限しますが、まだいくつかの文脈を提供するのに十分です。テキストの説明については、私は問題について尋ねます。私は特定のコードスニペットを参照しています。確かに、私は文字通りではなくコードを介してやろうとしたことを示していますが、私はそれがより明確であることを期待していました。私はbuild.sbtを提供すべきかどうか疑問に思っていましたが、十分なところで私の輸入を望んでいました。 –
それを除いて、徹底的な答えをありがとう!特に、未適用の定義は、どうやってそのようにするべきかを理解するのに役立ちます。構文的なノイズを減らすことが私の目標であると考えて、私はおそらく3つ目のアプローチを試し、他のマクロを呼び出す独自のマクロを作ることができるかどうかを確認します。 –
@OttidMes、質問についての部分は公平ではないかもしれませんが、私はそれに答えようとしている間に私が持っていた経験を共有しました。そして私は私の前に他の答えがないことは、あなたの質問が完全ではないことを示す兆候だと私は思う。私はまだあなたの意図のテキスト記述が** _ _ _ **であることを信じているので、私は "_それを書くよりもコードを読むのが難しいと思っています。(https://www.joelonsoftware .com/2000/04/06/things-you-should-never-do-part-i /)_ "のようになります。 – SergGr