- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读本教程 http://learnyouahaskell.com/a-fistful-of-monads并偶然发现了这个定义:
type KnightPos = (Int,Int)
moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = do
(c',r') <- [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)
,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)
]
guard (c' `elem` [1..8] && r' `elem` [1..8])
return (c',r')
in3 :: KnightPos -> [KnightPos]
in3 start = do
first <- moveKnight start
second <- moveKnight first
moveKnight second
in3
的问题(这需要棋盘上的一对坐标 (Int,Int) 并生成一个字段列表 [(Int,Int)] 可以在骑士的 3 次移动中从该字段到达。是否可能(如果是的话 - 如何这样做)将该功能改造成
inNMoves :: (Num a) => KnightPos -> a -> [KnightPos]
以便它还以移动次数作为参数,而不是恰好绑定(bind) 3 次跳跃?
最佳答案
由于这个练习是关于 List Monad 的,尽量不要去想你对 List 的了解,而是将自己限制在 monad 的结构上。所以那将是
move :: Monad m => Pos -> m Pos
move
需要一个
Pos
并给你一些关于
Pos
的东西某些 monadic 上下文中的事物
m
. (在列表的情况下,“上下文”是“任意多重性+排序”。但尽量不要考虑它)。
do
这里只是使用
(>>=)
的语法糖.出于本说明的目的,您需要知道如何使用
(>>=)
将 do 转换为表达式。 .
(>>=)
有签名
m a -> (a -> m b) -> m b
.我们需要的实例是
m Pos -> (Pos -> m Pos) -> m Pos
.你看我们已经实例化了
a
和
b
这里到
Pos
.您也可以识别中间部分
(Pos -> m Pos)
正在
move
在这里签名。所以使用
(>>=)
并给它
move
作为第二个参数,我们可以创建一个
m Pos -> m Pos
类型的函数.
moveM :: Monad m => m Pos -> m Pos
moveM mp = mp >>= move
m Pos -> m Pos
可以按您希望的顺序执行,因为它是从类型到自身的函数(我认为这可以称为 monad 内同态,因为类型是 monad)。
move2M :: Monad m => m Pos -> m Pos
move2M mp = moveM (moveM (mp))
move2M :: Monad m => m Pos -> m Pos
move2M = moveM . moveM
n
参数化的移动次数),我们只需要一些
moveM
s 由函数链操作符
.
连接.所以如果 n 是 3,我们想要
moveM . moveM . moveM
.以下是如何以编程方式执行此操作:
nmoveM :: Monad m => Int -> m Pos -> m Pos
nmoveM n = foldr1 (.) (replicate n moveM) -- n "moveM"s connected by (.)
foldr1
对于
n
的值未定义<= 0. 定义
nmoveM 0
很有意义到“什么都不做”。换句话说,恒等函数,
id
.
nmoveM :: Monad m => Int -> m Pos -> m Pos
nmoveM n = foldr (.) id (replicate n moveM)
foldr
而不是
foldr1
这需要一个额外的“基本案例”,
id
.
m Pos -> m Pos
,但我们想要
Pos -> m Pos
.这意味着,给定
Pos
,我们首先必须将其嵌入上下文
m
,然后执行
nMoveM
.这个嵌入运算符(我认为它可以称为初始代数)是
return
(类型
Monad m => a -> m a
)
nmoves :: Monad m => Int -> Pos -> m Pos
nmoves n = nmoveM n . return
nmoves :: Monad m => Int -> Pos -> m Pos
nmoves n = foldr (.) id (replicate n move) . return
(>>=)
实际上通常有点不干净,因为它是如此不对称:它需要一个
m a
和一个
a -> m b
.换句话说,它有点过于关心转换后的对象,而只关心我们案例的转换。这使得组合转换变得不必要地困难。这就是为什么我们不得不加入
. return
: 这是
Pos
的初始转换至
m Pos
,这样我们就可以自由组合任意数量的
m Pos -> m Pos
.
(>>=)
导致以下模式:
ma >>= f_1 >>= f_2 >>= ... >>= f_n
ma
是 monad 和
f_i
是
a -> m b
类型的“箭头” (通常 a = b)。
(>=>)
,它结合了两个
a -> m b
按序列键入箭头,并返回另一个箭头。
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
move
实际上是这样一个箭头(
Pos -> m Pos
)。所以
move >=> move >=> move >=> move >=> move
Pos -> m Pos
类型的有效表达式.使用
(>=>)
时,monad 的可组合特性变得更加明显。 .
nmoves
使用
(>=>)
像这样:
nmoves :: Monad m => Int -> Pos -> m Pos
nmoves n = foldr1 (>=>) (replicate n move) -- n "move"s connected by >=>
foldr1
,我们在问“是什么让 0 次连续移动”?它必须是相同的类型,
Pos -> m Pos
,答案是
return
.
nmoves :: Monad m => Int -> Pos -> m Pos
nmoves n = foldr (>=>) return (replicate n move)
nmoves
的定义进行比较在 monad 自同态世界中:代替函数与
(.)
结合使用和基本案例
id
,我们现在将箭头与
(>=>)
结合起来和基本案例
return
.好处是我们不必注入(inject)给定的
Pos
至
m Pos
.
(>=>)
比
(>>=)
干净多了.
关于Haskell 递归以 'do' 表示法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30471253/
在本教程中,您将借助示例了解 JavaScript 中的递归。 递归是一个调用自身的过程。调用自身的函数称为递归函数。 递归函数的语法是: function recurse() {
我的类(class) MyClass 中有这段代码: public new MyClass this[int index] { get {
我目前有一个非常大的网站,大小约为 5GB,包含 60,000 个文件。当前主机在帮助我将站点转移到新主机方面并没有做太多事情,我想的是在我的新主机上制作一个简单的脚本以 FTP 到旧主机并下载整个
以下是我对 AP 计算机科学问题的改编。书上说应该打印00100123我认为它应该打印 0010012但下面的代码实际上打印了 3132123 这是怎么回事?而且它似乎没有任何停止条件?! publi
fun fact(x: Int): Int{ tailrec fun factTail(y: Int, z: Int): Int{ if (y == 0) return z
我正在尝试用c语言递归地创建线性链表,但继续坚持下去,代码无法正常工作,并出现错误“链接器工具错误 LNK2019”。可悲的是我不明白发生了什么事。这是我的代码。 感谢您提前提供的大力帮助。 #inc
我正在练习递归。从概念上讲,我理解这应该如何工作(见下文),但我的代码不起作用。 请告诉我我做错了什么。并请解释您的代码的每个步骤及其工作原理。清晰的解释比只给我有效的代码要好十倍。 /* b
我有一个 ajax 调用,我想在完成解析并将结果动画化到页面中后调用它。这就是我陷入困境的地方。 我能记忆起这个功能,但它似乎没有考虑到动画的延迟。即控制台不断以疯狂的速度输出值。 我认为 setIn
有人愿意用通俗易懂的语言逐步解释这个程序(取自书籍教程)以帮助我理解递归吗? var reverseArray = function(x,indx,str) { return indx == 0 ?
目标是找出数组中整数的任意组合是否等于数组中的最大整数。 function ArrayAdditionI(arr) { arr.sort(function(a,b){ return a -
我在尝试获取 SQL 查询所需的所有数据时遇到一些重大问题。我对查询还很陌生,所以我会尽力尽可能地描述这一点。 我正在尝试使用 Wordpress 插件 NextGen Gallery 进行交叉查询。
虽然网上有很多关于递归的信息,但我还没有找到任何可以应用于我的问题的信息。我对编程还是很陌生,所以如果我的问题很微不足道,请原谅。 感谢您的帮助:) 这就是我想要的结果: listVariations
我一整天都在为以下问题而苦苦挣扎。我一开始就有问题。我不知道如何使用递归来解决这个特定问题。我将非常感谢您的帮助,因为我的期末考试还有几天。干杯 假设有一个包含“n”个元素的整数数组“a”。编写递归函
我有这个问题我想创建一个递归函数来计算所有可能的数字 (k>0),加上数字 1 或 2。数字 2 的示例我有两个可能性。 2 = 1+1 和 2 = 2 ,对于数字 3 两个 poss。 3 = 1+
目录 递归的基础 递归的底层实现(不是重点) 递归的应用场景 编程中 两种解决问题的思维 自下而上(Bottom-Up) 自上而下(Top-
0. 学习目标 递归函数是直接调用自己或通过一系列语句间接调用自己的函数。递归在程序设计有着举足轻重的作用,在很多情况下,借助递归可以优雅的解决问题。本节主要介绍递归的基本概念以及如何构建递归程序。
我有一个问题一直困扰着我,希望有人能提供帮助。我认为它可能必须通过递归和/或排列来解决,但我不是一个足够好的 (PHP) 程序员。 $map[] = array("0", "1", "2", "3")
我有数据 library(dplyr, warn.conflicts = FALSE) mtcars %>% as_tibble() %>% select(mpg, qsec) %>% h
在 q 中,over 的常见插图运算符(operator) /是 implementation of fibonacci sequence 10 {x,sum -2#x}/ 1 1 这确实打印了前 1
我试图理解以下代码片段中的递归调用。 static long fib(int n) { return n <= 1 ? n : fib(n-1) + fib(n-2); } 哪个函数调用首先被
我是一名优秀的程序员,十分优秀!