当前位置: 首页 > 知识库问答 >
问题:

线性类型允许为递归函数提供绑定解决方案

马胜泫
2023-03-14

线性类型的当前实现(GHC 9.0.1)存在限制,即let中的绑定不是线性的。

到目前为止,我已经能够使用用户指南中建议的显式函数来解决这个问题。然而,当试图实现函数时(出于好奇,来自ArrowLoop),我已经用完了变通方法。没有let或where绑定,如何引入递归?

loop :: ((b,d) ⊸ (c,d)) ⊸ b ⊸ c
loop f b = let (c,d) = f (b,d) in c

编辑

chi提供了一个令人信服的论点,即上述形式的循环是不可能的。以上在基于实例的基础上

class Category a => Arrow a where
    arr    :: (b ⊸ c) ⊸ a b c
    first  :: a b c ⊸ a (b,d) (c,d)
    second :: a b c ⊸ a (d,b) (d,c)
    (***)  :: a b c ⊸ a b' c' ⊸ a (b,b') (c,c')
    (&&&) :: (Dupable b) => a b c ⊸ a b c' ⊸ a b (c,c')

class Arrow a => ArrowLoop a where
    loop :: a (b,d) (c,d) ⊸ a b c

instance ArrowLoop (FUN 'One)

另一种定义是重新定义Arrow

class Category a => Arrow a where
    arr    :: (b -> c) ⊸ a b c
    ... as before ...

instance ArrowLoop (FUN 'Many) where
    -- loop :: ((b,d) -> (c,d)) ⊸ b -> c
    loop = let (c,d) = f (b,d) in c

这似乎也遇到了同样的问题,有点令人沮丧。箭头循环的最终可能定义为

instance ArrowLoop (FUN 'One) where
    -- loop :: ((b,d) ⊸ (c,d)) -> b ⊸ c
    loop = let (c,d) = f (b,d) in c

这只是非线性控件箭头循环的一个实例。箭头(有趣的一个)。这也是有问题的,因为使用了b

共有1个答案

景麒
2023-03-14

我认为这是不可能的。

它将允许您定义此实例:

{-# LANGUAGE LinearTypes, FlexibleInstances, UndecidableInstances #-}

import qualified Prelude.Linear as L

loop :: ((b, d) %1 -> (c, d)) %1 -> b %1 -> c
loop = undefined

instance L.Semigroup a => L.Consumable a where
  consume x = loop (\(y, z) -> (y, x L.<> z)) ()

(带序曲.线性线性基

因此,它基本上允许您仅通过一个函数来使用线性参数,该函数可以线性地组合该类型的两个参数。据我所知,这不是你应该被允许做的事情。

 类似资料:
  • 大家好,我正在尝试实现一个自定义TextView与字体。我决定使用RobotoTextView。我在资产中也有字体文件夹。我在时出错。 错误:

  • 我试图通过记忆来解决“计数变化”的问题。 考虑下面的问题:我们可以用多少种不同的方式来换取1美元,半价、四分之一、二分硬币、五分硬币和五分硬币?更一般地说,我们可以编写一个函数来计算使用任何一组货币面额改变任何给定金额的方法的数量吗? 以及递归的直观解决方案。 使用n种硬币改变a的数量的方法数 除第一种硬币外,其他所有硬币都可以换成硬币的方法,加上 使用所有n种硬币改变较小数量a-d的方法的数量,

  • 在下面的代码中,为什么允许绑定到函数? 演示 为什么允许这样做的直觉是什么,如何实现它,以及当您向传递一个lvalue参数,然后它调用接受rvalue引用的函数时,它实际上意味着什么?

  • 我试着用拉库OOP写杨彦湛的拉库谜语比赛答案。Raku类系统非常直观,在我遇到递归函数之前,一切都很有魅力。这是类和函数的代码版本: 对于$tigers=4,函数给出: 另一方面,类总是陷入无限循环。我相信函数和类之间的区别在于这行代码: 我不清楚这是因为格式错误的递归语法还是函数和类之间类型约束的差异。

  • 我有一个静态方法的类,如下所示: 如果我想打电话给Foo。foo并确保返回类型为,我可以说

  • 各种各样的书籍、文章、博客帖子表明,将递归函数重写为尾部递归函数可以加快速度。毫无疑问,对于生成斐波那契数或计算阶乘等琐碎情况,它会更快。在这种情况下,有一种典型的重写方法,即使用“辅助函数”和用于中间结果的附加参数。 尾部递归很好地描述了尾部递归函数和非尾部递归函数之间的差异,以及如何将递归函数转换为尾部递归函数。对于这种重写来说什么是重要的-函数调用的数量是相同的(重写之前/之后),不同之处在