简体   繁体   English

类型构造函数作为返回类型

[英]Type Constructor as Return Type

In Scala, I can define an Algebraic Data Type :在 Scala 中,我可以定义一个代数数据类型

scala> sealed trait Maybe[A]
defined trait Maybe

scala> case class Just[A](x: A) extends Maybe[A]
defined class Just

scala> case object NothingHere extends Maybe[Nothing]
defined object NothingHere

It's possible to return a function, f , with a return type of Maybe[A] .可以返回返回类型为Maybe[A]的函数f

scala> def f[A](x: A): Maybe[A] = Just(x)
f: [A](x: A)Maybe[A]

However, it's also possible to specify that a Just[A] is returned.但是,也可以指定返回Just[A]

scala> def f[A](x: A): Just[A] = Just(x)
f: [A](x: A)Just[A]

Now I'll do the similar exercise in Haskell:现在我将在 Haskell 中做类似的练习:

Prelude> data Option a = None | Some a deriving Show
Prelude> let f x = Some x :: Option Int
Prelude> f 10
Some 10

But, I can't set a return type of a type constructor .但是,我无法设置类型构造函数的返回类型。

Prelude> let f x = Some x :: Some Int

<interactive>:10:21:
    Not in scope: type constructor or class `Some'
    A data constructor of that name is in scope; did you mean DataKinds?
Prelude> let f x = None :: None

Is the simple difference that Scala's Just is a class, ie a legitimate return type? Scala 的Just是一个类,即合法的返回类型,这是一个简单的区别吗? Whereas, in Haskell, a type constructor cannot be a return type?而在 Haskell 中,类型构造函数不能是返回类型?

The difference is how Scala chose to implement ADTs.不同之处在于 Scala 选择实现 ADT 的方式。 Scala uses case classes that extend a trait in an OOP style, so each case is its own type, whereas Haskell just has multiple constructors for the same type. Scala 使用 case 类以 OOP 风格扩展特征,因此每个 case 都是它自己的类型,而 Haskell 只具有相同类型的多个构造函数。 Since they aren't separate types but essentially just separate functions, you can't distinguish them at the type level.由于它们不是单独的类型,而本质上只是单独的函数,因此您无法在类型级别区分它们。 There are extensions that give you some ability to make that type level distinction, but it won't be the same thing as what Scala has.有一些扩展可以让您进行类型级别的区分,但它与 Scala 所拥有的不同。 And trying to fit Haskell's type system into Scala's type system is probably not the best of ideas.尝试将 Haskell 的类型系统融入 Scala 的类型系统可能不是最好的主意。

In short, Scala approximates ADTs using a form of inheritance, whereas Haskell just has ADTs.简而言之,Scala 使用继承的形式来近似 ADT,而 Haskell 只有 ADT。

bhelkir and leftaroundabout have pointed out why you can't do this exactly in Haskell: there is no notion of subtypes. bhelkir 和 leftaroundabout 已经指出为什么你不能在 Haskell 中做到这一点:没有子类型的概念。

But note that with ADTs there are often alternatives that allow you achieve the same effect.但请注意,使用 ADT 时,通常有其他替代方案可以让您达到相同的效果。 In this case, one candidate technique would be to use the Void type in conjunction with Either :在这种情况下,一种候选技术是Void类型Either结合Either

import Data.Void

f :: Int -> Either Void Int
f x = Right x

Void is a type that has no defined values. Void是一种没有定义值的类型。 Therefore if you see the type Either Void a , that means that since there's no value x :: Void nobody can ever construct any value of the form Left x :: Either Void a .因此,如果您看到Either Void a类型,则意味着由于没有值x :: Void没有人可以构造Left x :: Either Void a形式的任何值。 (The exception is if x is a guaranteed nonterminating value, but we customarily ignore that possibility .) (例外情况是如果x是一个有保证的非终止值,但我们通常会忽略这种可能性。)

That means that an Either Void a is always of the form Right a , so for example, you can write this function:这意味着“ Either Void a ”的形式始终为“ Right a ,因此,例如,您可以编写以下函数:

-- | Extract the @a@ from @Either Void a@.
extract :: Either Void a -> a
extract (Left x) = absurd x
extract (Right a) = a

The absurd x there works basically like this: since x :: Void that means that there can never actually be a value for x , then absurd :: Void -> a , given its type, is a function that is impossible to ever call.absurd x那里的工作基本上是这样的:因为x :: Void即意味着永远实际上是一个值x ,那么absurd :: Void -> a ,因为它的类型,是一个函数,是不可能永远电话。 The way the type system works this means that it can claim to return any type at all that the caller expects.类型系统的工作方式意味着它可以声称返回调用者期望的任何类型。 See this question for some more discussion (though maybe a bit advanced).请参阅此问题以进行更多讨论(尽管可能有点高级)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM