You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell fp-course练习:如何将foldRight移至where子句?

如何正确提取List<*>实现中的内部foldRight到where子句?

我正在完成fp-course的函数式编程练习,List类型的<*>操作正确实现如下:

(<*>) fs as = foldRight (\f bs -> foldRight (\a bs -> f a :. bs) Nil as ++ bs) Nil fs

我尝试把内部的foldRight提取到where子句中,写出了如下代码,但出现错误:

(<*>) fs as = foldRight (\f bs -> f as ++ bs) Nil fs
                where f as = foldRight (\a bs -> f a :. bs) Nil as

报错信息如下:

src/Course/Applicative.hs:75:53: error:
    • Couldn't match type ‘a’ with ‘List a’
      Expected: List (List a -> List b)
        Actual: List (a -> b)
      ‘a’ is a rigid type variable bound by
        the type signature for:
          (<*>) :: forall a b. List (a -> b) -> List a -> List b
        at src/Course/Applicative.hs:(70,5)-(72,13)
    • In the third argument of ‘foldRight’, namely ‘fs’
      In the expression: foldRight (\ f bs -> f as ++ bs) Nil fs
      In an equation for ‘<*>’:
          (<*>) fs as
            = foldRight (\ f bs -> f as ++ bs) Nil fs
            where
                f as = foldRight (\ a bs -> f a :. bs) Nil as
    • Relevant bindings include
        as :: List a (bound at src/Course/Applicative.hs:75:12)
        fs :: List (a -> b) (bound at src/Course/Applicative.hs:75:9)
        (<*>) :: List (a -> b) -> List a -> List b
          (bound at src/Course/Applicative.hs:73:3)
   |
75 |   (<*>) fs as = foldRight (\f bs -> f as ++ bs) Nil fs
   |                                                     ^^

src/Course/Applicative.hs:76:25: error:
    • Couldn't match type ‘t1’ with ‘List t1’
      Expected: t1 -> t2
        Actual: List t1 -> List t2
      ‘t1’ is a rigid type variable bound by
        the inferred type of f :: t1 -> t2
        at src/Course/Applicative.hs:76:25-68
    • In an equation for ‘<*>’:
          (<*>) fs as
            = foldRight (\ f bs -> f as ++ bs) Nil fs
            where
                f as = foldRight (\ a bs -> f a :. bs) Nil as
      In the instance declaration for ‘Applicative List’
    • Relevant bindings include
        f :: t1 -> t2 (bound at src/Course/Applicative.hs:76:25)
   |
76 |                   where f as = foldRight (\a bs -> f a :. bs) Nil as
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, 10 modules loaded.

问题原因

核心问题是名字冲突:where子句里定义的f和外层lambda参数的f重名了。外层的f是fs中的元素,类型为a -> b;但你在where子句中将f定义为接收List a返回List b的函数,这导致类型匹配失败——外层lambda调用f as时,Haskell会优先绑定外层的f(类型a -> b),而非where子句中的函数,自然触发类型不匹配错误。

正确提取方式

给where子句中的函数换个不冲突的名字,比如applyF:

(<*>) fs as = foldRight (\f bs -> applyF f ++ bs) Nil fs
              where applyF f = foldRight (\a bs -> f a :. bs) Nil as

如果想让函数更通用,也可以把列表参数传入:

(<*>) fs as = foldRight (\f bs -> applyToAll f as ++ bs) Nil fs
              where applyToAll f xs = foldRight (\x ys -> f x :. ys) Nil xs

这样既完成了代码提取,又避免了名字冲突,类型也能正确匹配。

内容的提问来源于stack exchange,提问作者zichao liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:55:28