首页 > 解决方案 > 如何修改类型声明,这样我们就不必将 Either 更改为类型构造函数?

问题描述

{- data Either e a = Left e | Right a
   from the standard library.

   It's like Maybe, but the "no answer" case carries extra data, perhaps some kind
   of reason for why "no answer".
-}
fmap_Either :: (a -> b) -> (Either e) a -> (Either e) b
fmap_Either f (Left e) = Left e
fmap_Either f (Right a) = Right (f a)

这是我讲座中的一个例子。由于该函数只接受一个参数a,因此输出将变为 type b。我们必须更改Either e a为类型构造函数(Either e) a。我想知道我们是否可以修改函数,它将接受 2 个参数,以便我们可以编写Either e a而不是(Either e) a. 虽然我不确定这是否是个好主意。

标签: haskell

解决方案


我们可以修改函数吗,它将接受 2 个参数,以便我们可以编写Either e a而不是(Either e) a. 虽然我不确定这是否是个好主意。

情况已经如此,在HaskellEither e a(Either e) a. 前者只是去除了一些“噪音”,但如果你在窗帘后面写Either e a,你实际上已经写了(Either e) a

在 Haskell 中,每个函数都只接受一个参数。这也适用于类型构造函数:类型构造函数采用一个类型参数。如果我们因此编写需要两个或更多类型参数的类型,我们实际上已经编写了一个类型构造函数,它接受一种类型并生成一个新的“类型构造函数”,它将接受其他参数。

这个概念实际上在类型类中经常使用。以Functor类型类(定义fmap函数的类型类)为例:

class  Functor f where
    fmap        :: (a -> b) -> f a -> f b
    (<$)        :: a -> f b -> f a
    (<$)        =  fmap . const

我们在这里看到这f是一个接受类型参数的类型构造函数,因为在类型类的主体中,我们创建了类型f af b

如果我们再看看我们看到的Functor实例Either

instance Functor (Either e) where
    fmap _ (Left x) = Left x
    fmap f (Right y) = Right (f y)

(我替换(Either a)为,(Either e)因为声明中的 与定义中的不同a,因此避免混淆)instanceaclass

所以这里fEither e,因此f a将是一个(Either e) aEither e a


推荐阅读