为什么没有iterate定义为
iterate :: (a -> a) -> a -> [a]
iterate f x = xs where xs = x : map f xs
Run Code Online (Sandbox Code Playgroud)
在序曲?
我试图通过减少这个函数来包围Cont和callCC:
s0 = (flip runContT) return $ do
(k, n) <- callCC $ \k -> let f x = k (f, x)
in return (f, 0)
lift $ print n
if n < 3
then k (n+1) >> return ()
else return ()
Run Code Online (Sandbox Code Playgroud)
我设法达到了这一点:
s21 = runContT (let f x = ContT $ \_ -> cc (f, x) in ContT ($(f,0))) cc where
cc = (\(k,n) -> let
iff = if n < 3 then k (n+1) else ContT ($()) …Run Code Online (Sandbox Code Playgroud) 我们都知道递归定义的Fibonacci序列:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
?> fibs
[1,1,2,3,5,9,13,21,34,55,89...
Run Code Online (Sandbox Code Playgroud)
我试图在几个地方"修补"它,所以:
为此,我将定义以下函数来修改列表中的特定元素:
patch :: Int -> a -> [a] -> [a]
patch i v xs = left ++ v : right where (left,_:right) = splitAt i xs
Run Code Online (Sandbox Code Playgroud)
我可以用它来改变自然的顺序:
?> patch 5 0 [0..]
[0,1,2,3,4,0,6,7,8,9...
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.现在修补Fibonacci序列:
?> patch 1 0 fibs
[1,0,2,3,5,8,13,21,34,55,89...
Run Code Online (Sandbox Code Playgroud)
这符合要求(2).
为了获得(1),我将以更明确的结合风格重写定义:
fibs' p = rec where rec = p (1 : 1 : …Run Code Online (Sandbox Code Playgroud) 结点策略可用于构建图形,例如,使用简单的双边图形作为示例:
data Node = Node Node Node
-- a - b
-- | |
-- c - d
square = a where
a = Node b c
b = Node a d
c = Node a d
d = Node b c
Run Code Online (Sandbox Code Playgroud)
这个策略相当优雅,但是如果没有Int标签,我找不到实际使用它的方法.例如,我如何编写一个计算square值上节点数量的函数?
countNodes :: Node -> Int
countNodes = ... ??? ...
main = print $ countNodes square
-- output: 4
Run Code Online (Sandbox Code Playgroud) 我正在使用"打结"技术研究Haskell中的图形式事物处理.我想,循环列表只是一种无限列表内部实现,所以在理想世界中我们不应该关心subj.但它可能会对计算复杂性产生巨大影响,请考虑具有循环世界的一维元胞自动机示例:
ribbon = let x = 0 : y
y = 1 : x
in x
update_cycle :: Num a => [a] -> [a]
update_cycle lst@(_:xs) = ( f lst : update_cycle xs)
update_cycle [] = error "infinite cycle assumed"
f :: Num a => [a] -> a -- some arbitrary list reduction
f (x:(y:_)) = traceShow "f called" $ x - y
Run Code Online (Sandbox Code Playgroud)
这是一个只有两个单元格的循环.让我们迈出一步:
*Main> take 2 $ update_cycle ribbon
[-1,1]
"f called"
"f called"
Run Code Online (Sandbox Code Playgroud)
多数民众赞成,现在有两个步骤:
*Main> take 2 $ …Run Code Online (Sandbox Code Playgroud) haskell graph time-complexity tying-the-knot cyclic-dependency
我试图通过打结来形成像数据结构这样的无限网格.
这是我的方法:
import Control.Lens
data Grid a = Grid {_val :: a,
_left :: Grid a,
_right :: Grid a,
_down :: Grid a,
_up :: Grid a}
makeLenses ''Grid
makeGrid :: Grid Bool -- a grid with all Falses
makeGrid = formGrid Nothing Nothing Nothing Nothing
formGrid :: Maybe (Grid Bool) -> Maybe (Grid Bool) -> Maybe (Grid Bool) -> Maybe (Grid Bool) -> Grid Bool
formGrid ls rs ds us = center
where
center = Grid False leftCell …Run Code Online (Sandbox Code Playgroud) 下面的程序生成<<loop>>GHC。
...明显地。事后看来。
发生这种情况是因为walk正在计算一个不动点,但有多个可能的不动点。当列表推导式到达图形遍历的末尾时,它“询问” 的下一个元素answer;但这正是它已经在尝试计算的。我想我认为程序会到达,呃,列表的末尾,然后停止。
我不得不承认,我对这个漂亮的代码有点感伤,希望我能让它工作。
我应该怎么做?
我如何预测“打结”(指的是表示如何计算值的表达式中的值)是一个坏主意?
import Data.Set(Set)
import qualified Data.Set
-- Like `Data.List.nub`, remove duplicate elements from a list,
-- but treat some values as already having been seen.
nub :: Set Integer -> [Integer] -> [Integer]
nub _ [] = []
nub seen (x:xs) =
if Data.Set.member x seen
then nub seen xs
else x : nub (Data.Set.insert x seen) xs
-- A directed graph where the vertices are integers.
successors …Run Code Online (Sandbox Code Playgroud) Ross Paterson:Arrows and Computation介绍了该trace功能(第11页):
trace :: ((a, c) -> (b, c)) -> a -> b
trace f a = let (b, c) = f (a, c) in b
Run Code Online (Sandbox Code Playgroud)
该trace功能对于模拟循环程序中的魔术反馈步骤非常有用.例如,考虑Richard Bird的着名repmin函数,该函数查找树的最小叶值并创建一个相同的树,每个叶子值都替换为最小叶值,通过巧妙地使用惰性求值和局部递归(如提供者letrec):
data Tree = Leaf Int | Node Tree Tree deriving Show
repmin :: Tree -> Tree
repmin = trace repmin'
repmin' :: (Tree, Int) -> (Tree, Int)
-- put the minimum value m into the leaf …Run Code Online (Sandbox Code Playgroud) javascript haskell functional-programming lazy-evaluation tying-the-knot
在我最初尝试创建一个不相交的set数据结构时,我创建了一个Point带有parent另一个指针的数据类型Point:
data Point a = Point
{ _value :: a
, _parent :: Point a
, _rank :: Int
}
Run Code Online (Sandbox Code Playgroud)
要创建一个单例集,创建一个将Point其自身作为其父级的东西(我相信这称为绑结):
makeSet' :: a -> Point a
makeSet' x = let p = Point x p 0 in p
Run Code Online (Sandbox Code Playgroud)
现在,当我想写findSet(即跟随父指针,直到找到Point其父亲本身)我遇到了一个问题:是否有可能检查是否是这种情况?一个天真的Eq实例当然会无限循环 - 但是这个检查在概念上是否可以编写?
(我最终使用了一个Maybe Point用于父字段,请参阅我的另一个问题.)