需要什么才能让我的自定义ZipList应用程序实例进行编译?

The*_*Cat 1 haskell applicative

这是我用于创建自定义ZipList类的自定义List类.我想创建一个ZipList的应用实例.

import Control.Applicative

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

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

instance Applicative List where
  pure x = Cons x Nil
  (<*>) fs xs = Cons (head' fs $ head' xs) ((<*>) (tail' fs) (tail' xs))

head' :: List a -> a
head' (Cons a _) = a

tail' :: List a -> List a
tail' (Cons _ l) = l

take' :: Int -> List a -> List a
take' 0 _ = Nil
take' _ Nil = Nil
take' i xs = Cons (head' xs) (take' (i-1) (tail' xs))

newtype ZipList' a =
  ZipList' (List a)
  deriving (Eq, Show)

instance Functor ZipList' where
  fmap f (ZipList' xs) = ZipList' $ fmap f xs

instance Applicative ZipList' where
  pure x = ZipList' (Cons x Nil)
  (<*>) fs xs = ZipList' (go fs xs)
    where go gs ys = Cons (head' gs $ head' ys) (go (tail' gs) (tail' ys))
          go Nil _ = Nil
          go _ Nil = Nil
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

chap17/ZipList_applicative.hs:38:30: Couldn't match expected type ‘List (r0 -> b)’ …
                with actual type ‘ZipList' (a -> b)’
    Relevant bindings include
      xs :: ZipList' a
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:12)
      fs :: ZipList' (a -> b)
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:9)
      (<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:3)
    In the first argument of ‘go’, namely ‘fs’
    In the first argument of ‘ZipList'’, namely ‘(go fs xs)’
chap17/ZipList_applicative.hs:38:33: Couldn't match expected type ‘List r0’ …
                with actual type ‘ZipList' a’
    Relevant bindings include
      xs :: ZipList' a
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:12)
      fs :: ZipList' (a -> b)
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:9)
      (<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
        (bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:3)
    In the second argument of ‘go’, namely ‘xs’
    In the first argument of ‘ZipList'’, namely ‘(go fs xs)’
Compilation failed.
Run Code Online (Sandbox Code Playgroud)

它说它需要一个List(r0 - > b)类型,而不是ZipList'.我不明白为什么,返回一个List,而不是一个ZipList'......

And*_*ács 5

go需要ZipList作为输入,但在(<*>) fs xs xsfsZipList'秒.你应该解开newtype:

ZipList' fs <*> ZipList' xs = ZipList' (go fs xs)
Run Code Online (Sandbox Code Playgroud)

而且,你go错了.每当程序评估任一参数中的空列表时,它都会因运行时错误而失败,因为go gs ys大小写匹配所有内容,并且后面的案例无法访问.你应该做这样的事情:

go (Cons f fs) (Cons x xs) = Cons (f x) (go fs xs)
go _ _ = Nil
Run Code Online (Sandbox Code Playgroud)

作为一般规则,你应该避免head,tail和其他部分功能(即函数可能抛出异常).模式匹配Cons x xs结合两者的头部和尾部,所以不存在用于多大用处headtail此后.使用部分函数是非常合理的.