haskell - 线性类型让递归函数的绑定(bind)解决方法

标签 haskell linear-types

LinearTypes 的当前实现 (GHC 9.0.1) letwhere 绑定(bind)不是线性的。

到目前为止,我已经能够按照用户指南中的建议使用显式函数来解决这个问题。但是,在尝试实现功能时(出于好奇,来自 ArrowLoop),我已经用尽了所有变通方法。如何在没有 let 或 where 绑定(bind)的情况下引入递归?

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

这次好像遇到了同样的问题,有点郁闷。 ArrowLoop 的最终可能定义是

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

这只是 (FUN 'One) 的非线性 Control.ArrowArrowLoop 的一个实例。这也是有问题的,因为消耗了 b

最佳答案

我认为这是不可能的。

它将允许您定义这个实例:

{-# 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)) ()

(来自 linear-basePrelude.Linear)

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

关于haskell - 线性类型让递归函数的绑定(bind)解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68699408/

相关文章:

list - 将 0-s 添加到列表中,直到它的长度在 Haskell 中为 8

haskell - F# 相当于 Haskell scanl/scanr

haskell - Haskell 中的编号输出行

haskell - 线性类型如何防止 "duplicate"的这种实现?

linear-types - F* 是否支持线性类型?

haskell - 管理状态 - SICP 第 3 章

haskell - 从 "lens"的 map 获取多个结果

haskell - 为什么 Haskell 9.0 的线性类型没有零,而 Idris 2 有?

ocaml - OCaml 中的线性类型