首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实现自定义ZipList的应用程序

实现自定义ZipList的应用程序
EN

Stack Overflow用户
提问于 2019-10-28 15:02:20
回答 2查看 428关注 0票数 3

这来源于“Haskell”一书中的“基本原则”中的练习。练习是为Applicative实现ZipList',这类似于前奏曲的ZipList。这本书有这样的暗示

检查预存功能,这些函数可以满足您的需要。一个以字母z开头,另一个以字母r开头。您正在从这些函数中寻找灵感,而不能直接重用它们,因为您使用的是自定义List类型,而不是Prelude提供的列表类型。

我猜想以z开头的函数是zipWith,但我不知道以r开头的函数。

代码语言:javascript
运行
复制
data List a =
    Nil
  | Cons a (List a)
  deriving (Eq, Show)

zipWith' :: (a -> b -> c) -> List a -> List b -> List c
zipWith' _ Nil _ = Nil
zipWith' _ _ Nil = Nil
zipWith' f (Cons x xs) (Cons y ys) = Cons (f x y) (zipWith' f xs ys)

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
  (ZipList' fs) <*> (ZipList' xs) = ZipList' $ zipWith' ($) fs xs

这通过了书中的一个测试用例,但我想知道是否有更好的方法来实现它,因为我没有使用以r开头的函数。我有一种感觉,这应该是repeat,因为它也应该在无限列表上工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-28 20:08:45

我在Robin Zigmond's comment之后想了一会儿

关键是考虑合法的Applicative实例fmap f x == (pure f) <*> x的要求,并认识到列表x的长度没有上限。

这一实施应符合适用法律。

代码语言:javascript
运行
复制
data List a =
    Nil
  | Cons a (List a)
  deriving (Eq, Show)

zipWith' :: (a -> b -> c) -> List a -> List b -> List c
zipWith' _ Nil _ = Nil
zipWith' _ _ Nil = Nil
zipWith' f (Cons x xs) (Cons y ys) = Cons (f x y) (zipWith' f xs ys)

repeat' :: a -> List a
repeat' x = Cons x $ repeat' x

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' $ repeat' x
  (ZipList' fs) <*> (ZipList' xs) = ZipList' $ zipWith' ($) fs xs
票数 3
EN

Stack Overflow用户

发布于 2019-10-28 16:53:27

阅读原文下面的帖子,我得出了一个结论:文章的作者试图证明实现满足法律(fmap f xs = (pure f) <*> xs):

让我们试着证明它是一个经典标识,去掉包装器。因此,让我们用右手工作:

(pure f) <*> xs = (repeat' f) <*> xs = zipWith' ($) (repeat' f) xs

就身份而言,证明zipWith' ($) (repeat' f) xs等于fmap f xs就足够了。

它们相同的原因很明显:

length (zipWith op xs ys) == min (length xs) (length ys);(在xsys都是无限的情况下,不能计算这个表达式)。

由于repeat' f是无限的,length $ zipWith' ($) (repeat' f) xs实际上就是length xs (实际上,是否存在这样的值并不重要:索引的存在就足够了)。xs的每个元素都被应用到相同的函数f中,这是重复的。如您所见,大小保持不变,每个元素都由一个常量函数(即fmap的定义)进行变形。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58593349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档