有人可以向我解释依赖打字吗?我在Haskell,Cayenne,Epigram或其他函数式语言方面经验不足,因此您可以使用的术语越简单,我就越感激它!
我正在尝试为Haskell中的某个数据库系统设计一个API,我想以这样一种方式对这个数据库的列建模,使得不同表的列之间的交互不会混淆.
更确切地说,假设您有一个类型来表示数据库中的表,与某些类型相关联:
type Table a = ...
Run Code Online (Sandbox Code Playgroud)
并且您可以提取表的列以及列的类型:
type Column col = ...
Run Code Online (Sandbox Code Playgroud)
最后,有各种提取器.例如,如果您的表包含青蛙的描述,则可以使用函数提取包含青蛙重量的列:
extractCol :: Table Frog -> Column Weight
Run Code Online (Sandbox Code Playgroud)
这是一个问题:我想区分列的来源,以便用户不能在表之间进行操作.例如:
bullfrogTable = undefined :: Table Frog
toadTable = undefined :: Table Frog
bullfrogWeights = extractCol bullfrogTable
toadWeights = extractCol toadTable
-- Or some other columns from the toad table
toadWeights' = extractCol toadTable
-- This should compile
addWeights toadWeights' toadWeights
-- This should trigger a type error
addWeights bullfrogWeights toadWeights
Run Code Online (Sandbox Code Playgroud)
我知道如何在Scala中实现这一点(使用路径依赖类型,参见[1]),我一直在考虑Haskell中的3个选项:
不使用类型,只是在运行时进行检查(当前的解决方案)
TypeInType扩展,用于在Table类型本身上添加幻像类型,并将此额外类型传递给列.我并不热衷于此,因为这种类型的构造会非常复杂(表是通过复杂的DAG操作生成的),并且在这种情况下编译可能会很慢.
使用forall类似于ST monad 的构造包装操作,但在我的情况下,我希望额外的标记类型实际上逃避构造. …
Scala具有路径依赖类型,但据说Scala不支持依赖类型.路径依赖类型和依赖类型之间有什么区别?
据我所知,路径依赖类型是一种依赖类型.
我注意到Scala标准库使用两种不同的策略来组织类,特征和单例对象.
使用其成员为导入的包.例如,这是您访问的方式scala.collection.mutable.ListBuffer.这种技术很熟悉来自Java,Python等.
使用特征的类型成员.例如,这是您访问该Parser类型的方式.你首先需要混入scala.util.parsing.combinator.Parsers.这种技术不熟悉来自Java,Python等,并且在第三方库中使用不多.
我猜(2)的一个优点是它组织了方法和类型,但根据Scala 2.8的包对象,可以使用(1)完成相同的操作.为什么要有这两种策略?什么时候应该使用?
我目前正在研究Scala中的A*实现.为了实现一个干净的结构,我想使用一个嵌套的case类结构,它实现了一个自我限制的特征.但是,在Scala IDE中实现它时遇到了一些问题.以下代码将无法编译:
trait A[T <: A[T]]
class B {
case class C(int: Int) extends A[C] // A[this.C] won't work either
def make = C(5)
}
object D {
def foo[T <: A[T]](some: T) = {}
val c = new B().make
foo(c) // this does not compile
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以使这个结构有效吗?
我有一个内部案例类,特别是来自这个问题的事件,并且想要匹配它,包括外部对象:
class Player {
var _life = 20
def life = _life
def gainLife(life: Int) = execute(GainLife(life))
case class GainLife(life: Int) extends Event {
def execute() = _life += life
}
}
Run Code Online (Sandbox Code Playgroud)
我可以轻松编写一个替换特定玩家生活事件的效果(部分功能):
//gain twice as much life
def effect(player: Player): ReplacementEffect = {
case player.GainLife(x) => player.GainLife(x * 2)
}
Run Code Online (Sandbox Code Playgroud)
但是,对于其他玩家我不能这样做.我最接近的是:
//only you gain life
def effect2(player: Player): ReplacementEffect = {
case evt: Player#GainLife => player.GainLife(evt.life)
}
Run Code Online (Sandbox Code Playgroud)
但是1)这甚至取代了你自己的生活费用新的生活费用,2)我不能引用最初在功能中获得生命的玩家和3)我错过了直接匹配life这种方式.
这可以使用与路径无关的类型表示
case Player.GainLife(_player, life) if _player != …Run Code Online (Sandbox Code Playgroud)