对于所有类型scala3(种类限制错误)

sqxo8psd  于 6个月前  发布在  Scala
关注(0)|答案(1)|浏览(64)

我正在尝试用Scala编写一个名为'Rock'的Haskell库中的一些核心数据库。
正如上面链接项目的README中所提到的,库的想法大致基于here的论文。
以下是Rock库(Haskell)中使用的核心类型:

// in src/Core.hs (
type Rules f = GenRules f f

-- | A function which, given an @f@ query, returns a 'Task' allowed to make @g@
-- queries to compute its result.
type GenRules f g = forall a. f a -> Task g a

-- | An @IO@ action that is allowed to make @f@ queries using the 'fetch'
-- method from its 'MonadFetch' instance.
newtype Task f a = Task { unTask :: ReaderT (Fetch f) IO a }
  deriving
    (Functor, Applicative, Monad, MonadIO, MonadBase IO, MonadFix)

newtype Fetch f = Fetch (forall a. f a -> IO a)

字符串
有些看起来比构建系统中的那些更简单(例如:Task类型,它是IO上的瘦抽象)
我很好奇在Scala中以类似的方式建模是否可能/可行。
在对Scala中的“forall”类型做了一些阅读之后(并参考了旧的线程,如this one),我从以下内容开始:

object Core {

  type Rules[F[_]] = GenRules[F[_], F[_]]  //<- scala err: "Type argument F[?] does not have the same kind as its bound [_$2]"

  type GenRules[F[_], G[_]] = [A] => (F[_] => Task[G[_], A])

  type Task[F[_], A] = ReaderT[Fetch[F[_]], A]

  type Fetch[F[_]] = /*forall*/ [A] => (F[A] => IO[A])

}


我很难理解为什么我不能用F[_]专门化GenRules类型.
还有:接下来,无论这些类型在Scala 3(或2)中采用何种形式,我们的目标都是复制Rock repo主页中演示的电子表格示例。

// Spreadsheet.hs (https://github.com/ollef/rock/blob/master/examples/Spreadsheet.hs)
data Query a where
  A :: Query Integer
  B :: Query Integer
  C :: Query Integer
  D :: Query Integer

rules :: Rock.Rules Query
rules key = do
  liftIO $ putStrLn $ "Fetching " <> show key
  case key of
  ...             -- rest elided


Scala版本:

// GADT for the sample/example `Query` type
enum Query[A]:
    case A extends Query[Int]
    case B extends Query[Int]
    case C extends Query[Int]
    case D extends Query[Int]

def rules() : Core.Rules[Query] =
   // ????


在原始的haskell代码中,rules函数中提到的keyQuery a类型。有一点:rules函数不接受输入。。那么Core.Rules[Query]是某种部分应用的类型吗?
任何对这些问题的深入了解都是有帮助的--我并不一定关心达到“惯用”的Scala代码

57hvy0tb

57hvy0tb1#

类型参数定义中的F[_]表示“类型构造函数 * -> *"。类型应用程序中的F[_]表示“存在类型”。Scala 3倾向于为这些类型使用两种不同的语法,但Scala 2中的旧语法仍然会被解析。在F应用程序中删除[_],因为它的友好性与预期不符。
GenRules应该应用从[A] =>获得的A

// definitions in more sane order
object Core {
  type Fetch[F[_]] = [A] => F[A] => IO[A]

  type Task[F[_], A] = ReaderT[IO, Fetch[F], A]
                  // = Fetch[F] => IO[A] (what this ReaderT actually is)

  type GenRules[F[_], G[_]] = [A] => F[A] => Task[G, A])
                         // = [A] => F[A] => ReaderT[IO, Fetch[G], A] (dealias)

  type Rules[F[_]] = GenRules[F, F]
                // = [A] => F[A] => ReaderT[IO, Fetch[F], A] (dealias)
}

字符串
一旦我们做了去锯齿练习,我们就知道我们需要定义什么样的值:

val rules: Core.Rules[Query] =
  [A] => (key: Query[A]) => {
    // here create value of type:
    // Task[Query, A] dealiased to
    // ReaderT[IO, Fetch[Query], A]
    ???
  }


编辑:
实际上,如果我们进一步去别名,一个实现变得有点明显:

val rules: Core.Rules[Query] =
  [A] => (key: Query[A]) =>
    ReaderT[IO, Fetch[Query], A] {
   // (fetch: Fetch[Query]) =>
      (fetch: [B] => Query[B] => IO[B]) =>
        fetch[A](key) // IO[A]
    }


这里你有一个类型参数方法,它接受值(键),然后接受另一个类型参数方法来应用该值。由于Rules的类型是多态函数,它接受参数的事实在它的定义中是隐藏的,但是当你示例化它时,你必须以某种方式传递这些参数。然后你会定义。在Haskell中,所有函数都是curry的,所以如果你只定义了第一个参数,那么就假定你将返回一些会消耗剩余参数的东西。

相关问题