首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我自己的数据类型的应用函子(Haskell)

我自己的数据类型的应用函子(Haskell)
EN

Stack Overflow用户
提问于 2022-07-22 11:43:40
回答 1查看 154关注 0票数 1

我正在努力理解哈斯克尔,我被困在“无法构造无限类型”的-error中。

我想为我自己的数据类型实现"<*>“,模仿列表的行为。

到目前为止,我的功能代码:

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

instance Functor (List) where
--  fmap :: (Functor f) => (a -> b) -> f a -> f b
    fmap f Nil = Nil
    fmap f (Cons a (b)) = Cons (f a) (fmap f b)

现在,我正在尝试创建一个“应用程序列表”实例:

代码语言:javascript
复制
instance Applicative List where
    pure a = Cons a (Nil)
--  (<*>) :: f (a -> b) -> f a -> f b
    (Cons a (b)) <*> (Cons c (d)) = Cons (fmap a (Cons c (d))) (b <*> (Cons c (d)))
    (Nil) <*> _ = Nil
    _ <*> (Nil) = Nil

目标是定义“<*>”,以便模拟列表的行为。示例:

代码语言:javascript
复制
 (fmap (*)) [5,6,3] <*> [0,2]
--> [0,10,0,12,0,6]

因此,它应该创造:

代码语言:javascript
复制
(fmap (*)) (Cons 5 (Cons 6 (Cons 3 (Nil)))) <*> (Cons 0 (Cons 2 (Nil)))
--> (Cons 0 (Cons 10 (Cons 0 (Cons 12 (Cons 0 (Cons 6 (Nil))))))))

但不幸的是,我遇到了一个非常无用的错误:

代码语言:javascript
复制
10-3.hs:14:65: error:
    * Occurs check: cannot construct the infinite type: b ~ List b
      Expected type: List (List b)
        Actual type: List b
    * In the second argument of `Cons', namely `(b <*> (Cons c (d)))'
      In the expression: Cons (fmap a (Cons c (d))) (b <*> (Cons c (d)))
      In an equation for `<*>':
          (Cons a (b)) <*> (Cons c (d))
            = Cons (fmap a (Cons c (d))) (b <*> (Cons c (d)))
    * Relevant bindings include
        b :: List (a -> b) (bound at 10-3.hs:14:14)
        a :: a -> b (bound at 10-3.hs:14:11)
        (<*>) :: List (a -> b) -> List a -> List b (bound at 10-3.hs:14:18)
   |
14 |     (Cons a (b)) <*> (Cons c (d)) = Cons (fmap a (Cons c (d))) (b <*> (Cons c (d)))
   |                                                                 ^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.

我不知道为什么需要一个列表(List (List b)),因为我的数据类型的定义清楚地声明了一个正常的列表是Cons的第二个参数。

我希望有人能帮我这个忙!

编辑:谢谢你,这解决了它。现在这可能是一个非主题的话题,但是我试图复制用于解决这个问题的列表的原始语法。其在“前奏曲”一揽子方案中的定义如下:

代码语言:javascript
复制
instance Applicative [] where
    {-# INLINE (<*>) #-}
    fs <*> xs = [f x | f <- fs, x <- xs]

因为我不能使用列表理解,至于我不想创建一个实际的列表(shure,我可以只是转换它以后,但我不喜欢这个想法)。我用lambdaBot翻译了语法糖,得到了以下内容:

代码语言:javascript
复制
fs <*> xs = concatMap (\ f -> concatMap (\ x -> [f x]) xs) fs

是否有办法这样做,或者这本质上等同于使用附加(助手)-function来完成它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-22 11:52:59

在冒犯的那一行:

代码语言:javascript
复制
  (Cons a (b)) <*> (Cons c (d)) = Cons (fmap a (Cons c (d))) (b <*> (Cons c (d)))

子表达式fmap a (Cons c (d))List b类型,您正在尝试将它放到(b <*> (Cons c (d)))上,(b <*> (Cons c (d)))也具有List b类型。但是请记住,类型是Cons :: a -> List a -> List a。注意,Cons的第一个元素需要是一个元素,第二个元素应该是一个列表。因此,编译器假设您的元素类型本身是List b,然后报告它希望第二个参数具有List (List b)类型。

要解决这个问题,您应该编写一个Cons函数,而不是使用append :: List a -> List a -> List a函数:

代码语言:javascript
复制
  (Cons a (b)) <*> (Cons c (d)) = append (fmap a (Cons c (d))) (b <*> (Cons c (d)))

关于语法,请注意:您可以使代码更清晰一些,如下所示:

代码语言:javascript
复制
  Cons f fs <*> xs = append (fmap f xs) (fs <*> xs)

提示:

something.

  • Avoid

  • 为函数使用具有暗示性的名称(如f ),并在冗余模式列表的末尾添加s,以匹配(Cons c (d)) ->冗余括号。特别是,您不必在变量(如(d).和(b) )周围使用括号。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73079820

复制
相关文章

相似问题

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