什么是< $>和< *>哈斯克尔的操作数

时间:2016-12-06 19:20:07

标签: haskell operators

haskell中的那些运营商是什么?和< *> 我把他们排成一行:

class Evaluable e where
    eval :: (Num a, Ord a) => (Ident -> Maybe a) -> (e a) -> (Either String a)
    typeCheck :: (Ident -> String) -> (e a) -> Bool

instance Evaluable NExpr where
    eval lookup (Plus left right) = (+) <$> eval lookup left <*> eval lookup right

3 个答案:

答案 0 :(得分:4)

由于我是showed you these operators的人,我将简要说明我使用它们的原因。

要查看,仿函数是一种类型构造函数,它允许您使用fmap函数将函数应用于“包装”值。在Either类型构造函数的特定情况下(部分应用,在本例中为String),您可以将函数应用于Right值,但如果应用于函数则忽略该函数一个Left值(您的错误)。它提供了一种错误传播方式,而无需检查错误。

fmap f (Right x) = Right (f x)
fmap f (Left y) = Left y

应用仿函数是类似的,除了函数本身可以像它应用的参数一样被包装。 <*>运算符解包它的两个操作数,不像fmap只会解包它的右操作数。

Right f <*> Right x = Right (f x)
Left f <*> _ = Left f
_ <*> Left y = Left y

通常,您不会自己包装函数:它们是使用fmap将函数部分应用于包装值而产生的:

fmap (+) (Right 3) == Right (+ 3)
fmap (+) (Left "error") == Left "error"

因此,当我们使用Either值时,使用<$>(中缀fmap)和<*>让我们假装我们正在处理常规值,担心他们是否被LeftRight包裹着。 Right值提供预期的Right - 包装答案,并保留Left个值。对于二元运算符,只返回第一个Left值,但这通常就足够了。

(+) <$> Left "x undefined" <*> Left "y undefined" == Left "x undefined" <*> Left "y undefined"
                                                  == Left "x undefined"

(+) <$> Left "x undefined" <*> Right 9 == Left "x undefined" <*> Right 9
                                       == Left "x undefined"

(+) <$> Right 3 <*> Left "y undefined" == Right (+ 3) <*> Left "y undefined"
                                       == Left "y undefined"

(+) <$> Right 3 <*> Right 9 == Right (+3) <*> Right 9
                            == Right 12

最后,使用Applicative Either String实例让我们结合评估两个子表达式的结果,而无需显式检查eval的递归调用是否实际成功。成功的递归调用会带来成功;任何一个呼叫中的错误都被用作顶级呼叫的相同错误。

答案 1 :(得分:3)

<$>运算符是fmap的中缀形式。它允许您将纯函数应用于包含在属于Functor类的某个参数类型中的值。 <$>的类型为(a -> b) -> f a -> f b

<*>运算符与<$>非常相似。它允许您将包含在参数类型中的函数应用于包含在相同参数类型中的值。 <*>的类型为f (a -> b) -> f a -> f b

答案 2 :(得分:1)

在这种特殊情况下,它是一种结合eval结果的方法。 如果表达式的一部分失败,那么整个表达式都会失败。

这样,它可以分离应用程序逻辑的错误处理并避免复杂的嵌套case ... of

要完全理解这一点,我建议先阅读有关仿函数的内容,然后再阅读适用的仿函数。

与此同时,您可以使用Maybe和Either,并使用case表达式编写等效代码。