簡體   English   中英

我如何將循環寫為lambda函數?

[英]How would I write cycle as a lambda function?

只是為了好玩,這是我自己的cycle版本:

myCycle :: [a] -> [a]
myCycle xs = xs ++ myCycle xs

右側是指函數名稱myCycle和參數xs

是否可以在提及myCyclexs 情況下實現myCycle

myCycle = magicLambdaFunction

是否可以在不提及myCyclexs情況下實現myCycle

答案是肯定而不是(不一定按順序)。

其他人提到了定點組合器。 如果你有一個定點組合器fix :: (a -> a) -> a ,那么正如你在對Pubby的答案的評論中提到的那樣,你可以編寫myCycle = fix . (++) myCycle = fix . (++)

fix的標准定義是這樣的:

fix :: (a -> a) -> a
fix f = let r = f r in r

-- or alternatively, but less efficient:
fix' f = f (fix' f)

請注意, fix的定義涉及在其定義的右側提及左側變量(第一個定義中的r ,第二個定義中的“ fix' )。 所以到目前為止我們真正做的就是把問題推到了fix

有趣的是,Haskell基於一個類型化的lambda演算,並且出於技術上的原因,大多數類型的lambda演算被設計成使得它們不能 “原生地”表達固定點組合。 如果您在基礎演算的“頂部”添加一些允許計算固定點的額外功能,這些語言只會變成圖靈完備。 例如,其中任何一個都可以:

  1. fix作為基元添加到微積分中。
  2. 添加遞歸數據類型(Haskell具有;這是在Haskell中定義fix另一種方式)。
  3. 允許定義引用正在定義的左側標識符(Haskell也有)。

由於許多原因,這是一種有用的模塊化類型 - 一種是沒有固定點的lambda演算也是邏輯的一致證明系統,另一種可以證明在許多這樣的系統中無需fix程序可以終止。


編輯:這是用遞歸類型編寫的fix 現在fix本身的定義不是遞歸的,但Rec類型的定義是:

-- | The 'Rec' type is an isomorphism between @Rec a@ and @Rec a -> a@:
--
-- > In  :: (Rec a -> a) -> Rec a
-- > out :: Rec a        -> (Rec a -> a)
--
-- In simpler words:
--
-- 1. Haskell's type system doesn't allow a function to be applied to itself.
--
-- 2. @Rec a@ is the type of things that can be turned into a function that
--    takes @Rec a@ arguments.
--
-- 3. If you have @foo :: Rec a@, you can apply @foo@ to itself by doing
--    @out foo foo :: a@.  And if you have @bar :: Rec a -> a@, you can do 
--    @bar (In bar)@.
--
newtype Rec a = In { out :: Rec a -> a }

-- | This version of 'fix' is just the Y combinator, but using the 'Rec'
-- type to get around Haskell's prohibition on self-application (see the
-- expression @out x x@, which is @x@ applied to itself):
fix :: (a -> a) -> a
fix f = (\x -> f (out x x)) (In (\x -> f (out x x)))

我認為這有效:

myCycle = \xs -> fix (xs ++)

http://en.wikipedia.org/wiki/Fixed-point_combinator

在支持匿名函數的編程語言中,定點組合器允許定義和使用匿名遞歸函數,即不必將這些函數綁定到標識符。 在此設置中,定點組合器的使用有時稱為匿名遞歸。

為了好玩,這是另一回事:

let f = foldr (++) [] . repeat 

要么

let f = foldr1 (++) . repeat

沒有人指出修復解決方案的“明顯”版本。 我們的想法是將命名的遞歸調用轉換為參數。

let realMyCycle = fix (\myCycle xs -> xs ++ myCycle xs)

這種“遞回域名”引入招是相當多的東西let in確實在Haskell。 唯一的區別是使用內置構造更直接,並且可能更好地實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM