实例适用于数据类型“列表”

时间:2018-10-27 15:30:41

标签: haskell applicative

Haskell的《 Haskell从第一原理编程》一书中有一个练习,要求我在数据类型Applicative上实例化List

data List a =
  Nil
  | Cons a (List a)
  deriving (Eq, Show)

instance Functor List where
  fmap _ Nil = Nil
  fmap f (Cons x xs) = Cons (f x) (fmap f xs)

instance Applicative List where
  pure x = Cons x Nil
  Nil <*> _ = Nil
  _ <*> Nil = Nil
  Cons f fs <*> Cons x xs = Cons (f x) ((fmap f xs) <> (fs <*> xs))

我编写了以上代码,发现必须首先实例Semigroup才能使<>运算符起作用。

可以在没有实例Semigroup的情况下实现吗?

2 个答案:

答案 0 :(得分:2)

。您在此处在定义中使用>>> class Foo(int): __slots__ = () def __new__(cls, a, b, c, add=True): value = cls.sum(a, b, c) if add else cls.subtract(a, b, c) return super().__new__(cls, value) @staticmethod def sum(a, b, c): return a + b + c @staticmethod def subtract(a, b, c): return c - b - a >>> foo = Foo(1, 2, 3, True) >>> foo 6 >>> type(foo) <class '__main__.Foo'> 函数:

(<>)

因此您可以将其替换为对另一个函数的调用:

instance Applicative List where
    pure x = Cons x Nil
    Nil <*> _ = Nil
    _ <*> Nil = Nil
    Cons f fs <*> Cons x xs = Cons (f x) ((fmap f xs) <> (fs <*> xs))
    --                                               ^ call to the (<>) function

但是请注意,在这里您可能实现的功能与您在此处打算实现的功能不同。在这里,您实现了一个针对两个列表instance Applicative List where pure x = Cons x Nil Nil <*> _ = Nil _ <*> Nil = Nil Cons f fs <*> Cons x xs = Cons (f x) (append (fmap f xs) (fs <*> xs)) where append = ...[f1, f2, f3]的函数,该函数将使用[x1, x2, x3, x4]fs的矩阵的“上三角”来计算一个列表,因此结果为xs。请注意,这里缺少[f1 x1, f1 x2, f1 x3, f1 x4, f2 x2, f2 x3, f2 x4, f3 x3, f3 x4]f2 x1f3 x1

答案 1 :(得分:0)

好吧,您使用了一种叫做<>的东西,Haskell知道,这件事(特别是您导入的<>的定义是因为您在任何地方都没有定义运算符)需要一个半组。解决方案是使用其他名称或在本地定义它:

Cons f fs <*> xs = (f <$> xs) <> (fs <*> xs)
    where xs <> Nil = xs
          Nil <> xs = xs
          Cons x xs <> ys = Cons x (xs <> ys)