你知道我如何循环函数func2 10次吗?
type Vertex = Int
type OutNeighbors = [Vertex]
data Graph = Graph [(Vertex,OutNeighbors)] deriving (Eq, Show, Read)
func2 (Graph g) = filter (\x -> contains (fst x) (func1 (Graph g))) g --I need to repeat this function 10 times.我对haskell有点陌生,我不知道该怎么做循环。
发布于 2021-07-07 07:28:55
你知道我如何循环函数
func210次吗?
> take 5 $ iterate ("hi " ++) "there!"
["there!","hi there!","hi hi there!","hi hi hi there!","hi hi hi hi there!"]
> let func2 = (+3) in iterate func2 0 !! 10
30但这将需要func2返回与其输入相同的类型,而且现在它似乎具有类型。
func2 :: Graph -> [(Vertex,OutNeighbors)]但如果你把Graph包回去,也就是说,
func2 :: Graph -> Graph
func2 (Graph g) = Graph (... g)然后你就可以在上面iterate了。
发布于 2021-07-07 07:29:28
在Haskell中,可以对循环使用递归,下面是一个示例:
myLoop 0 g = g
myLoop n g = myLoop (n - 1) (Graph (func2 g))现在,调用myLoop 10 g将在g上调用func2 10次。
请注意,我必须将结果包装回Graph类型,这可能是您应该在func2函数中做的事情:
func2 (Graph g) = Graph (filter (\x -> contains (fst x) (func1 (Graph g))) g)如果您从State包中将其封装在transformers monad中,您可以获得更高的级别:
import Control.Monad.Trans.State.Lazy (execState, modify)
import Control.Monad (replicateM_)
myLoop :: Int -> Graph -> Graph
myLoop n g = execState (replicateM_ n (modify func2)) g发布于 2021-07-07 12:19:03
这是这样一种情况,为了避免输入错误,您需要能够通过正确的名称引用整个参数及其子组件。
幸运的是,Haskell提供了这一点。这被称为“ as patterns”。这里有更多的细节:苏-q 30326249。
在您的例子中,您可以注意到您的图形参数为:g@(Graph(pairs))。然后,g是您的图形对象,pairs是对应的[(Vertex,OutNeighbors)]类型列表。
您没有告诉我们您的contains函数,但是可以推断它的类型是:
contains :: Vertex -> Graph -> Bool考虑到这一点,可以这样编写任意迭代计数的图形函数的版本:
type Vertex = Int
type OutNeighbors = [Vertex]
data Graph = Graph [(Vertex,OutNeighbors)] deriving (Eq, Show, Read)
funcN :: Int -> Graph -> Graph
funcN iterCount g@(Graph(pairs)) =
if (iterCount <= 0) then g -- nothing to do
else let
gm1 = funcN (iterCount - 1) g -- recursion
fn = \(v,ngs) -> contains v gm1 -- filtration
in
Graph (filter fn pairs)使用同样的技术,contains函数的暂定版本如下所示:
contains :: Vertex -> Graph -> Bool
contains v g@( Graph [] ) = False
contains v g@( Graph ((v0,ngs0):pairs) ) = (v == v0) || contains v (Graph(pairs))第二个函数有点复杂,因为列表可以通过2种模式来描述,即空的和非空的。
最后,可以这样编写执行10次迭代的函数的版本:
func10 :: Graph -> Graph
func10 g = funcN 10 g或者以更简洁的方式使用部分应用程序(在Haskell圈中称为竞逐):
func10 :: Graph -> Graph
func10 = funcN 10增编:库式,使用nest
如果出于某种原因,“手动递归”被拒绝,则可以使用nest :: Int -> (a -> a) -> a -> a库函数。它使用内部递归计算函数的N个组合幂。
然后,只需编写图函数的单个迭代版本。代码如下所示:
import Data.Function.HT (nest)
funcNl :: Int -> Graph -> Graph
funcNl iterCount g0 = let
-- 2 local function definitions:
ftfn g1 (v, ngs) = contains v g1
func1 g2@(Graph(pairs)) = Graph (filter (ftfn g2) pairs)
in
nest iterCount func1 g0https://stackoverflow.com/questions/68281549
复制相似问题