我正在寻找一种在不需要实际数据时简化功能模式的方法:
data X = A | B String | C Int Int String
myfn :: X -> Int
myfn A = 50
myfn (B _) = 200
myfn (C _ _ _) = 500
Run Code Online (Sandbox Code Playgroud)
有没有办法为匹配C制作一个更简单的模式,只是丢弃这些值?
hsdev添加了一个提示"提示:使用记录模式",但谷歌并没有帮助我.
我遇到了Haskell的问题.我的文本文件看起来像这样:
5.
7.
[(1,2,3),(4,5,6),(7,8,9),(10,11,12)].
Run Code Online (Sandbox Code Playgroud)
我不知道如何获得前两个数字(上面的2和7)和最后一行的列表.每行末尾有点.
我试图构建一个解析器,但是名为'readFile'的函数返回Monad,称为IO String.我不知道如何从这种类型的字符串中获取信息.
我更喜欢在一系列字符上工作.也许有一个函数可以从'IO String'转换为[Char]?
我已经在函数式语言中看到很多关于处理列表和构造函数的函数,这些函数在接收到一些额外的值(通常在生成函数时不存在)时对其元素执行某些操作,例如:
("懒惰评估"下的最后两个例子)
暂存列表以严格的函数语言(如ML/OCaml)附加,以避免多次遍历第一个列表
(标题为"暂存"的部分)
使用foldr将列表与另一个列表进行比较(即生成将另一个列表与第一个列表进行比较的函数)
listEq a b = foldr comb null a b
where comb x frec [] = False
comb x frec (e:es) = x == e && frec es
cmp1To10 = listEq [1..10]
Run Code Online (Sandbox Code Playgroud)在所有这些例子中,作者通常只注意遍历原始列表一次的好处.但是我不能让自己不要"确定,而不是遍历N个元素列表,而是遍历一系列N个评估,那又怎么样?".我知道必须有一些好处,有人可以解释一下吗?
编辑:感谢两者的答案.不幸的是,这不是我想知道的.我会试着澄清我的问题,所以它并没有与(更常见的)关于创建中间列表(我已经在不同的地方读过)相混淆.还要感谢我纠正我的帖子格式.
我对构造要应用于列表的函数的情况感兴趣,在该列表中,您还没有必要的值来评估结果(无论是否为列表).然后,您无法避免生成对每个列表元素的引用(即使列表结构不再被引用).并且您拥有与以前相同的内存访问权限,但您不必解构列表(模式匹配).
例如,请参阅上述ML书中的"分段"章节.我在ML和Racket中尝试过它,更具体地说是"追加"的阶段版本,它遍历第一个列表并返回一个函数,在尾部插入第二个列表,而不会多次遍历第一个列表.令我惊讶的是,即使考虑到它仍然必须复制列表结构,因为最后一个指针在每种情况下都不同,所以它要快得多.
以下是map的变体,应用于列表后,更改函数时应该更快.由于Haskell不严格,我将不得不强制评估listMap [1..100000]in cachedList(或者可能不是,因为在第一次应用之后它应该仍然在内存中).
listMap = foldr comb (const [])
where comb x rest = \f -> f x : rest f
cachedList = listMap [1..100000]
doubles = cachedList (2*)
squares = cachedList (\x -> …Run Code Online (Sandbox Code Playgroud) 我是Haskell的新手,遇到麻烦<*>:
((==) <*>) :: Eq a => (a -> a) -> a -> Bool
Run Code Online (Sandbox Code Playgroud)
我如何理解这一点以及如何推断它?
以尽可能少的字符生成Fibonacci序列.任何语言都可以,除了您使用一个运算符定义的语言f,它会打印斐波那契数字.
起点:25 14个字符的哈斯克尔:
f=0:1:zipWith(+)f(tail f)
f=0:scanl(+)1f
Run Code Online (Sandbox Code Playgroud) 澄清问题:它是关于monad类型类的优点(而不是它没有统一类的实例).
在阅读了许多参考文献(见下文)之后,我得出的结论是,实际上,monad类只能解决一个问题,即大而重要的问题:关于具有上下文的类型的函数的"链接".因此,着名的句子"monad是可编程的分号".实际上,monad可以被视为具有辅助操作的函数数组.
我坚持monad 类之间的区别,被理解为其他类型的通用接口; 以及这些其他类型实例化类(因此,"monadic类型").
我理解monad类本身只解决了运算符的链接,因为主要是它只要求它的类型实例具有bind >>=和return,并且告诉我们它们必须如何表现.作为奖励,编译器非常有助于编码为monadic do类型提供符号.
另一方面,实例化monad类的每个单独类型解决了每个具体问题,但不仅仅是作为Monad的实例.例如,Maybe解决"函数如何返回值或错误",State解决"如何使用全局状态的函数",IO解决"如何与外部世界交互"等等.所有这些类都在上下文中封装了一个值.
但不久之后,我们需要对这些上下文类型进行连锁操作.也就是说,我们需要以特定的顺序组织对这些类型的函数的调用(对于这样一个问题的例子,请阅读你可能已经发明了monad的多值函数的例子).
如果每个类型都是monad类的实例,那么你就解决了链接的问题.为了使链接起作用,你需要>>=具有它所具有的确切签名,而不是其他.(见这个问题).
因此,我猜你下次定义上下文数据类型T来解决问题时,如果你需要对函数的调用进行排序(在T的值上),可以考虑将T作为一个实例Monad(如果你需要"选择链接",如果你可以从do符号中受益).为了确保你做得对,检查T是否符合monad法则
然后,我向Haskell专家提出两个问题:
函数
f由f(n) = nifn < 3和f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3)if 的规则定义n > 3.编写一个f通过递归过程计算的过程.编写一个f通过迭代过程计算的过程.
递归地实现它很简单.但我无法弄清楚如何迭代地做到这一点.我尝试与给出的Fibonacci示例进行比较,但我不知道如何将其用作类比.所以我放弃了(羞辱我)并用Google搜索解释,我发现了这个:
(define (f n)
(if (< n 3)
n
(f-iter 2 1 0 n)))
(define (f-iter a b c count)
(if (< count 3)
a
(f-iter (+ a (* 2 b) (* 3 c))
a
b
(- count 1))))
Run Code Online (Sandbox Code Playgroud)
阅读之后,我理解代码及其工作原理.但我不明白的是从函数的递归定义到此需要的过程.我不明白代码是如何在某个人的头脑中形成的.
你能解释一下解决方案所需的思考过程吗?
我编写了以下代码,它使用光泽库获取了一堆点并在屏幕上绘制它们.
let s = blocks pes
pts = map (map mkPt) s {- stitches to points-}
lines = map Line pts {-points to lines -}
pict = Pictures lines {- lines to a picture -}
in do displayInWindow "My Window" (200, 200) (10, 10) white pict
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我发现有一个重复的模式:一个函数调用链,每个函数调用的结果进入下一个参数的最后一个参数.所以我通过删除中间变量,反转顺序并使用函数组合(".")链接函数来重构,如下所示:
let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict
Run Code Online (Sandbox Code Playgroud)
令人高兴的是,这也很好.但是我想知道我是否会降低可读性,或者我是不是习惯于阅读和编写点免费样式代码.另外,我如何推理这段代码?第二个版本更有效率,还是仅仅更高效?有什么我可以风格化的做法让它更清晰吗?
我在一个Scheme类中,我很好奇在不使用define的情况下编写递归函数.当然,主要的问题是,如果没有名称,你就无法调用自身内部的函数.
我确实找到了这个例子:它是一个只使用lambda的阶乘生成器.
((lambda (x) (x x))
(lambda (fact-gen)
(lambda (n)
(if (zero? n)
1
(* n ((fact-gen fact-gen) (sub1 n)))))))
Run Code Online (Sandbox Code Playgroud)
但我甚至无法理解第一次调用,(lambda(x)(xx)):究竟是做什么的?你在哪里输入你想要得到的阶乘值?
这不是为了上课,这只是出于好奇.