小编Wil*_*ess的帖子

Haskell记录模式匹配

我正在寻找一种在不需要实际数据时简化功能模式的方法:

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 record pattern-matching algebraic-data-types

29
推荐指数
1
解决办法
8797
查看次数

如何在Haskell中解析IO String?

我遇到了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]?

string io monads parsing haskell

28
推荐指数
4
解决办法
2万
查看次数

避免多个列表遍历的好处

我已经在函数式语言中看到很多关于处理列表和构造函数的函数,这些函数在接收到一些额外的值(通常在生成函数时不存在)时对其元素执行某些操作,例如:

在所有这些例子中,作者通常只注意遍历原始列表一次的好处.但是我不能让自己不要"确定,而不是遍历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 functional-programming ml

28
推荐指数
3
解决办法
891
查看次数

如何在Haskell中理解":t((==)<*>)"?

我是Haskell的新手,遇到麻烦<*>:

((==) <*>) :: Eq a => (a -> a) -> a -> Bool
Run Code Online (Sandbox Code Playgroud)

我如何理解这一点以及如何推断它?

haskell types type-inference ghc

28
推荐指数
1
解决办法
2930
查看次数

斐波那契代码高尔夫

以尽可能少的字符生成Fibonacci序列.任何语言都可以,除了您使用一个运算符定义的语言f,它会打印斐波那契数字.

起点:25 14个字符哈斯克尔:

f=0:1:zipWith(+)f(tail f)

f=0:scanl(+)1f
Run Code Online (Sandbox Code Playgroud)

language-agnostic code-golf fibonacci rosetta-stone

27
推荐指数
16
解决办法
6150
查看次数

"链接操作"是Monad课程解决的"唯一"问题吗?

澄清问题:它是关于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专家提出两个问题:

  1. 一个具体的问题:monad类是否有任何其他问题解决(离开monadic类)?那么,它与链接操作问题的相关性如何?
  2. 一个可选的一般问题:我的结论是对的,我是否误解了什么?

参考

教程

StackOverflow问题与解答

monads haskell functional-programming

27
推荐指数
2
解决办法
1247
查看次数

不知道如何解决SICP练习1.11

练习1.11:

函数ff(n) = nif n < 3f(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)

阅读之后,我理解代码及其工作原理.但我不明白的是从函数的递归定义到此需要的过程.我不明白代码是如何在某个人的头脑中形成的.

你能解释一下解决方案所需的思考过程吗?

iteration recursion scheme sicp

25
推荐指数
2
解决办法
5645
查看次数

点免费代码更有效率,还是只是更简洁?

我编写了以下代码,它使用光泽库获取了一堆点并在屏幕上绘制它们.

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)

令人高兴的是,这也很好.但是我想知道我是否会降低可读性,或者我是不是习惯于阅读和编写点免费样式代码.另外,我如何推理这段代码?第二个版本更有效率,还是仅仅更高效?有什么我可以风格化的做法让它更清晰吗?

refactoring haskell coding-style pointfree

25
推荐指数
1
解决办法
1245
查看次数

在Scheme中,如何使用lambda创建递归函数?

我在一个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)):究竟是做什么的?你在哪里输入你想要得到的阶乘值?

这不是为了上课,这只是出于好奇.

recursion lambda scheme anonymous-recursion

25
推荐指数
5
解决办法
1万
查看次数

我如何确定我的GHC版本?

这可能是一个非常愚蠢的问题,但我似乎无法找到答案......

haskell version ghc

25
推荐指数
3
解决办法
9139
查看次数