我试图绕着固定点和递归定义弯曲.
这有效:
>>> take 10 $ let x = (0:x) in x
[0,0,0,0,0,0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)
这也是一样的,考虑到以下定义,这是有意义的fix:
>>> take 10 $ fix (\x -> (0:x))
[0,0,0,0,0,0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)
现在假设我开始乱搞递归定义的对:
>>> take 10 $ fst $ let (u,v) = (0:v,1:u) in (u,v)
[0,1,0,1,0,1,0,1,0,1]
Run Code Online (Sandbox Code Playgroud)
好的,我也应该能够写出来fix,对吧?
>>> take 10 $ fst $ fix (\(u,v) -> (0:v,1:u))
*** Exception: <<loop>>
Run Code Online (Sandbox Code Playgroud)
但它不起作用.除非我做出以下看似微不足道的改变:
>>> take 10 $ fst $ fix (\r -> let (u,v)=r in (0:v,1:u))
[0,1,0,1,0,1,0,1,0,1]
Run Code Online (Sandbox Code Playgroud)
最后两个例子之间的关键区别是什么?
我发现规范的tr.func.require部分需要std::function在C++ 11中可以复制构造,我已经看到了很多解释为什么这意味着用于构造的仿函数std::function必须是可复制的,但为什么C++ 11标准首先是可std::function复制的,而不是让它成为仅移动类型?
所以,我正在编写一个小帮助函数来进行广度优先搜索(只是一个爱好项目):
import Control.Monad.State
import qualified Data.Set as S
breadthFirst :: (Monad m, Ord a) => (a -> m [a]) -> [a] -> m ()
breadthFirst f init = evalStateT (go init) S.empty
where
go :: [a] -> StateT (S.Set a) m ()
go [] = return ()
go (x:xs) = do
visited <- gets (S.member x)
if visited then (go xs) else do
modify (S.insert x)
lift (f x) >>= (\n -> go (xs++n))
Run Code Online (Sandbox Code Playgroud)
即拉出队列状态,运行f以获得更多状态并将它们放回队列,使用a Set来跟踪访问状态以及任何副作用m …