Any reason why scala does not explicitly support dependent types?

后端 未结 4 1969
长发绾君心
长发绾君心 2020-11-28 17:54

There are path dependent types and I think it is possible to express almost all the features of such languages as Epigram or Agda in Scala, but I\'m wondering why Scala does

4条回答
  •  一个人的身影
    2020-11-28 18:27

    The question was about using dependently typed feature more directly and, in my opinion, there would be a benefit in having a more direct dependent typing approach than what Scala offers.
    Current answers try to argue the question on type theoretical level. I want to put a more pragmatic spin on it. This may explain why people are divided on the level of support of dependent types in the Scala language. We may have somewhat different definitions in mind. (not to say one is right and one is wrong).

    This is not an attempt to answer the question how easy would it be to turn Scala into something like Idris (I imagine very hard) or to write a library offering more direct support for Idris like capabilities (like singletons tries to be in Haskell).

    Instead, I want to emphasize the pragmatic difference between Scala and a language like Idris.
    What are code bits for value and type level expressions? Idris uses the same code, Scala uses very different code.

    Scala (similarly to Haskell) may be able to encode lots of type level calculations. This is shown by libraries like shapeless. These libraries do it using some really impressive and clever tricks. However, their type level code is (currently) quite different from value level expressions (I find that gap to be somewhat closer in Haskell). Idris allows to use value level expression on the type level AS IS.

    The obvious benefit is code reuse (you do not need to code type level expressions separately from value level if you need them in both places). It should be way easier to write value level code. It should be easier to not have to deal with hacks like singletons (not to mention performance cost). You do not need to learn two things you learn one thing. On a pragmatic level, we end up needing fewer concepts. Type synonyms, type families, functions, ... how about just functions? In my opinion, this unifying benefits go much deeper and are more than syntactic convenience.

    Consider verified code. See:
    https://github.com/idris-lang/Idris-dev/blob/v1.3.0/libs/contrib/Interfaces/Verified.idr
    Type checker verifies proofs of monadic/functor/applicative laws and the proofs are about actual implementations of monad/functor/applicative and not some encoded type level equivalent that may be the same or not the same. The big question is what are we proving?

    The same can me done using clever encoding tricks (see the following for Haskell version, I have not seen one for Scala)
    https://blog.jle.im/entry/verified-instances-in-haskell.html
    https://github.com/rpeszek/IdrisTddNotes/wiki/Play_FunctorLaws
    except the types are so complicated that it is hard to see the laws, the value level expressions are converted (automatically but still) to type level things and you need to trust that conversion as well. There is room for error in all of this which kinda defies the purpose of compiler acting as a proof assistant.

    (EDITED 2018.8.10) Talking about proof assistance, here is another big difference between Idris and Scala. There is nothing in Scala (or Haskell) that can prevent from writing diverging proofs:

    case class Void(underlying: Nothing) extends AnyVal //should be uninhabited
    def impossible() : Void = impossible()
    

    while Idris has total keyword preventing code like this from compiling.

    A Scala library that tries to unify value and type level code (like Haskell singletons) would be an interesting test for Scala's support of dependent types. Can such library be done much better in Scala because of path-dependent types?

    I am too new to Scala to answer that question myself.

提交回复
热议问题