【问题标题】:Haskell Tabulate function using Foldmap "Out of Scope"使用 Foldmap“超出范围”的 Haskell 制表函数
【发布时间】:2020-08-17 09:48:22
【问题描述】:

我正在尝试为“制表”编写一个定义,该函数会生成给定 Map 中值的单曲面摘要 对应于给定可折叠集合中的键。

这是我的代码:

module Foldables where

import Prelude hiding (Applicative(..), any, concat)
import Data.Foldable
import Data.Semigroup

import qualified Data.Map as Map
import Data.Map (Map)
import Data.Map.Append (AppendMap(..))
import Data.List (intersperse)
import Data.Maybe (maybe)
import Data.Monoid (Any(..), Sum(..))
import GHC.Generics (Generic)

tabulate :: (Ord k, Foldable f, Monoid a) => (v -> a) -> Map k v -> f k -> a
tabulate t m = foldMap (tabulate . k v)

我收到此错误:

src/Foldables.lhs:295:27: error:
    • Data constructor not in scope: Tabulate :: b0 -> a
    • Perhaps you meant variable ‘tabulate’ (line 295)

src/Foldables.lhs:295:38: error:
    Variable not in scope: k :: t0 -> k -> b0

除了第二行括号中的内容外,请不要更改任何内容

更新:我想我更接近于理解这一点。这是我的新代码。我意识到它不完整,但它至少可以编译。

tabulate :: (Ord k, Foldable f, Monoid a) => (v -> a) -> Map k v -> f k -> a
tabulate t m = foldMap (\x -> mempty maybe [m] maybe map [t])

现在它没有通过阴谋集团测试:

   Falsified (after 2 tests):
     <fun>
     fromList [(False,'\DC4'),(True,'\1054302')]
     [True,True]

无论我做什么,似乎都会有一些变化

如果 tabulate 的第三个参数不是空的,我假设我需要的是某种条件?

【问题讨论】:

  • 请添加Tabulate的定义(即提供minimal reproducible example
  • 抱歉,我应该更具体一些。这是制表的定义。我在开头行添加了这一点,并且还包括了我所有的导入。
  • 除了@Ackdari 的问题,第二行的kv 代表什么?
  • 地图的变量
  • @steve 我看不到 kv 的绑定位置,因为您传递的参数是 tm。此外,我看不出如何将一个应用于另一个。

标签: haskell monoids ord tabulate foldable


【解决方案1】:

这是一个提示(这是一个没有foldMap的解决方案,我认为这是问题的对象):

如果我没听错的话,你想写下这样的内容:

tabulate :: (Ord k, Foldable t, Monoid a) => (v -> a) -> Map k v -> t k -> a
tabulate t m ks = let
                    c k x = (t <$> Data.Map.Strict.lookup k m) <> x
                  in case Prelude.foldr c Nothing ks of
                          Just s  -> s
                          Nothing -> mempty

ks 的交集(顺便说一下,foldMap 的解决方案不需要这个参数 - 它会被删除,正如你在帖子中想要的那样)与地图的键 (m) 为空(即只收集了 Nothings)。

在其他情况下,我们只是用一些东西折叠键的容器,类似于mappend for Maybe - 它首先尝试在地图中查找给定的键。如果成功,它将结果放入Just,然后将fmaps 转换为t(给我们一个幺半群)放入其中。如果没有,则返回Nothing。在Maybes 的mappend-sequence 中,所有Nothings 都被丢弃,Justs 中的结果与mappend 连接。对于Maybe,请参见&lt;&gt; 的定义(&lt;&gt;Semigroup 的方法,它是mappend 的基础,因为MonoidSemigroup 的子类):

-- | @since 4.9.0.0
instance Semigroup a => Semigroup (Maybe a) where
    Nothing <> b       = b
    a       <> Nothing = a
    Just a  <> Just b  = Just (a <> b)
    ...

我的解决方案foldMap

tabulate :: (Ord k, Foldable t, Monoid a) => (v -> a) -> Map k v -> t k -> a
tabulate t m = foldMap (\ k -> maybe mempty t (Data.Map.Strict.lookup k m))

它执行以下操作:foldMap 的函数参数采用密钥 k。如果它不在地图中,则返回mempty。否则 - 它返回t x,其中Just xlookup 得到的。

【讨论】:

  • 当我尝试使用时,我得到:不在范围内:'Data.Map.lookup'
  • @steve 另外,我看过你最新的编辑。使用maybe 是正确的想法。如果这是您喜欢的方法,我会将其添加到我的答案中。无论如何,你想尝试一下这个问题,还是我应该编辑我的帖子,用foldMap替换foldr
  • @steve 对不起-名字的错是我的错。我的ghc 版本太旧了——你应该使用Data.Map.Strict.lookup(你应该在你的导入中添加Data.Map.Strict)。
  • 如果你不介意用 foldmap 显示;我已经尝试了所有我想到的组合。如果您知道如何在不导入任何内容的情况下执行此操作,那就更好了。
  • @steve 当然,我已将其添加到帖子中。名称问题解决了吗(因为我仍然使用lookup)?
猜你喜欢
  • 1970-01-01
  • 2021-11-29
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2010-11-22
相关资源
最近更新 更多