比较Haskell的数据构造函数与Scala的子类

时间:2016-01-13 17:41:59

标签: scala haskell

假设我的应用有两种类型的错误:

λ: data AppError = FailedLogin | InvalidMessage deriving Show

它有loginsendMessage个函数:

λ: let login user pw = Left FailedLogin :: Either AppError String
λ: let sendMessage msg token = Left InvalidMessage :: Either AppError Int
λ: login "foo" "bar" >>= (\token -> sendMessage "hello world" token)
Left FailedLogin

但请注意,返回类型为Either AppError String。我无法指定Either FailedLogin ...

λ: let f = Left FailedLogin :: Either FailedLogin String

<interactive>:18:36:
    Not in scope: type constructor or class ‘FailedLogin’
    A data constructor of that name is in scope; did you mean DataKinds?

这种行为的原因是什么,即无法在Either的{​​{1}}类型中使用数据构造函数?

其次,假设我在Scala中重现了上述代码:

Left

请注意,我可以将scala> sealed trait AppError defined trait AppError scala> case object FailedLogin extends AppError defined object FailedLogin scala> case object InvalidMessage extends AppError defined object InvalidMessage scala> def login(user: String, password: String): Either[FailedLogin.type, String] = ??? login: (user: String, password: String)Either[FailedLogin.type,String] 指定为返回类型。如果我需要致电:FailedLogin,那就没有意义了。但是,如果我只期望login >>= sendMessage的{​​{1}}上有一个值,那么使用Either是不是惯用的?或者是否值得创建一个具有单个子类的Left,引用case object s Left中的特征?

1 个答案:

答案 0 :(得分:2)

简要说明:e中的aEither e a都需要是类型。您正在使用需要类型的值。 FailedLogin类型AppErrorAppError 构造函数中的一个是FailedLogin

构造函数是创建某种类型值的方法。因此,对于任何数据类型data X = A | B | C ... Z,我们可以使用其任何构造函数来创建类型X的值。

例如,Maybe a是一种类型,Just是其构造函数之一:

> :t Just 1
Just 1 :: Num a => Maybe a

Nothing也是Maybe的构造函数之一。

> :t Nothing
Nothing :: Maybe a

类型始终位于数据类型的左侧,而构造函数位于右侧。

我无法谈论.type在Scala中的工作原理,但我认为在Scala中正确使用和类型只会说AppError而不是FailedLogin。如果FailedLogin真正独立,它应该是它自己的特质。