首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Haskell中循环a函数10次

在Haskell中循环a函数10次
EN

Stack Overflow用户
提问于 2021-07-07 07:12:12
回答 3查看 470关注 0票数 1

你知道我如何循环函数func2 10次吗?

代码语言:javascript
复制
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有点陌生,我不知道该怎么做循环。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-07-07 07:28:55

你知道我如何循环函数func2 10次吗?

您可以在10点iterate it和!!

代码语言:javascript
复制
> 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返回与其输入相同的类型,而且现在它似乎具有类型。

代码语言:javascript
复制
func2 :: Graph -> [(Vertex,OutNeighbors)]

但如果你把Graph包回去,也就是说,

代码语言:javascript
复制
func2 :: Graph -> Graph
func2 (Graph g) = Graph (... g)

然后你就可以在上面iterate了。

票数 1
EN

Stack Overflow用户

发布于 2021-07-07 07:29:28

在Haskell中,可以对循环使用递归,下面是一个示例:

代码语言:javascript
复制
myLoop 0 g = g
myLoop n g = myLoop (n - 1) (Graph (func2 g))

现在,调用myLoop 10 g将在g上调用func2 10次。

请注意,我必须将结果包装回Graph类型,这可能是您应该在func2函数中做的事情:

代码语言:javascript
复制
func2 (Graph g) = Graph (filter (\x -> contains (fst x) (func1 (Graph g))) g)

如果您从State包中将其封装在transformers monad中,您可以获得更高的级别:

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2021-07-07 12:19:03

这是这样一种情况,为了避免输入错误,您需要能够通过正确的名称引用整个参数及其子组件。

幸运的是,Haskell提供了这一点。这被称为“ as patterns”。这里有更多的细节:苏-q 30326249

在您的例子中,您可以注意到您的图形参数为:g@(Graph(pairs))。然后,g是您的图形对象,pairs是对应的[(Vertex,OutNeighbors)]类型列表。

您没有告诉我们您的contains函数,但是可以推断它的类型是:

代码语言:javascript
复制
contains :: Vertex -> Graph -> Bool

考虑到这一点,可以这样编写任意迭代计数的图形函数的版本:

代码语言:javascript
复制
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函数的暂定版本如下所示:

代码语言:javascript
复制
contains :: Vertex -> Graph -> Bool
contains v g@( Graph [] )                 =  False
contains v g@( Graph ((v0,ngs0):pairs) )  =  (v == v0)  ||  contains v (Graph(pairs))

第二个函数有点复杂,因为列表可以通过2种模式来描述,即空的和非空的。

最后,可以这样编写执行10次迭代的函数的版本:

代码语言:javascript
复制
func10 :: Graph -> Graph
func10 g = funcN 10 g

或者以更简洁的方式使用部分应用程序(在Haskell圈中称为竞逐):

代码语言:javascript
复制
func10 :: Graph -> Graph
func10 = funcN 10

增编:库式,使用nest

如果出于某种原因,“手动递归”被拒绝,则可以使用nest :: Int -> (a -> a) -> a -> a库函数。它使用内部递归计算函数的N个组合幂。

然后,只需编写图函数的单个迭代版本。代码如下所示:

代码语言:javascript
复制
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 g0
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68281549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档