gpt4 book ai didi

haskell - 从 Integral a => ([a],[a],[a]) 的值中获取 Integral a => [a] 类型的值

转载 作者:行者123 更新时间:2023-12-03 14:53:26 28 4
gpt4 key购买 nike

所以我在玩这个:

factors :: Integral a => a -> [a] 
factors n = filter (\d -> n `rem` d == 0) . takeWhile (\d -> d*d <= n) $ [ 1 .. ]

abundants_perfects_deficients :: Integral a => ([a],[a],[a])
abundants_perfects_deficients = foldr switch ([],[],[]) [1..]
where switch :: Integral a => a -> ([a],[a],[a]) -> ([a],[a],[a])
switch n (as,ps,ds) =
let t = sum (factors n) in
if t < n then (as,ps,n:ds)
else if t == n then (as,n:ps,ds)
else (n:as,ps,ds)

虽然我有 abundants_perfects_deficients ,我宁愿有三个值: abundants , perfects , 和 deficients所有类型 Integral a -> [a] .

不起作用的一件事是:
abundants,perfects,deficients :: Integral a => [a] 
(abundants,perfects,deficients) = abundants_perfects_deficients

因为这限制了三个都在同一个 a .

我尝试了一些事情来一对一地做,所以它们不会相互约束,但这也不起作用:
perfects :: Integral a => [a] 
(_,perfects,_) = abundants_perfects_deficients

因为编译器不知道如何转换 forall a. Integral a => ([a],[a],[a]) 类型的值。输入 (t1, forall a. Integral a => [a], t2) .

这似乎足够美味。

现在我知道我可以单独实现它们(只是 perfects = filter isPerfect [1..] ),或者将它们限制为都属于同一类型( (abundants,perfects,deficients) = abundants_perfects_deficients 如果 abundants,perfects,deficients :: [Integer] 可以正常工作),但是
  • 我喜欢使用共享信息来构建所有三个
  • 我不想仅仅局限于 Integer小号

  • 想法?

    编辑 : 令人着迷的是,这很有效:
    abundants :: Integral a => [a]
    abundants = f as
    where as :: [Integer]
    (as,_,_) = abundants_perfects_deficients
    f :: Integral a => [Integer] -> [a]
    f = map fromInteger

    但这不会:
    abundants_perfects_deficients' :: (Integral a,Integral p, Integral d) => ([a],[p],[d])
    abundants_perfects_deficients' = (f as, f ps, f ds)
    where as,ps,ds :: [Integer]
    (as,ps,ds) = abundants_perfects_deficients
    f :: Integral a => [Integer] -> [a]
    f = map fromInteger

    abundants,perfects,deficients :: (Integral a) => [a]
    (abundants,perfects,deficients) = abundants_perfects_deficients'

    我不知道为什么。

    最佳答案

    这与多态类型的真正含义有关,这比它们最初出现的方式稍微复杂一些。

    在这一点上,可能更容易切换思维模式并将量词视为 lambda 抽象的一种形式:像 ∀ a. [a] 这样的类型因此是一个接受单个类型参数的函数,并返回该类型的事物列表。类约束,如 Integral a可以看作是 GHC 为您找到值时隐式提供的附加参数(特别是实例字典)。

    为了强调这一点,我将把量词写成 /\ a ->模仿 lambda 语法,并将类约束编写为常规参数。

    这样写,abundants_perfects_deficients 的类型是 /\a -> Integral a -> ([a],[a],[a]) ,并且您的初始尝试基本上失败了,因为您试图对两个参数函数的结果进行模式匹配。在许多情况下,GHC 会自动调整这些隐含的参数以使事情顺利进行,但在这里它显然不能——从 abundants_perfects_deficients 获得任何结果。你首先需要将它应用于两个参数,得到一个单态结果,然后使用模式绑定(bind)。即使模式只绑定(bind)一个值,其余的也是 _ , GHC 仍然需要对模式绑定(bind)本身进行类型检查,所以即使看起来额外的参数可以 float 到单个绑定(bind)标识符,这与一次绑定(bind)所有三个的原因相同。

    要将三个多态值与模式绑定(bind),您需要将额外的参数放在内部,从而为 Famouss_perfects_deficients 提供一个类似于 (/\a -> Integral a -> [a], /\a -> Integral a -> [a], /\a -> Integral a -> [a]) 的类型。 .这需要 the ImpredicativeTypes extension ,它的过去有些曲折,我仍然对此保持警惕。

    很多让你感到困惑的是,GHC 不够聪明,无法找出“显而易见”的东西,比如 float 隐式类型和约束参数,它们仅在绑定(bind)的特定部分中使用。考虑到它在幕后已经做了多少魔法,这并没有让我太困扰。 :]

    最简单的解决方案是单独绑定(bind)所有三个,使用选择函数来提取各个元素。这让顶级绑定(bind)以预期的方式多态,它接收到的隐式参数隐式传递给 abundants_perfects_deficients ,并且投影函数在(现在是单态的)模式匹配之后简单地丢弃其他三个。

    关于haskell - 从 Integral a => ([a],[a],[a]) 的值中获取 Integral a => [a] 类型的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7473472/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com