Haskell嵌套了where子句和"let ... in"语法

use*_*355 3 haskell

我刚刚开始使用Haskell.

这个嵌套的where子句有什么问题?

length' a = fromIntegral (length a)

isPalin1 xs = fstHalf == reverse sndHalf
    where
        fstHalf = take halfLength xs
        sndHalf = drop halfLength xs
            where halfLength = (length' xs) / 2
Run Code Online (Sandbox Code Playgroud)

我得到的错误: isPalin1.hs:5:32: Not in scope: ‘halfLength’

以下也是错误的,希望有人可以告诉我原因:

length' a = fromIntegral (length a)

isPalin2 xs = fstHalf == reverse sndHalf
    where
        let
            halfLength = (length' xs) / 2
        in
            fstHalf = take halfLength xs
            sndHalf = drop halfLength xs
Run Code Online (Sandbox Code Playgroud)

错误消息:

isPalin2.hs:7:17:
    parse error (possibly incorrect indentation or mismatched brackets)
Run Code Online (Sandbox Code Playgroud)

AJF*_*mar 6

where仅适用于一个绑定,因此halfLength在您的第一个片段中仅可用于sndHalf.你应该这样写:

length' a = fromIntegral (length a)

isPalin1 xs = fstHalf == reverse sndHalf
    where
        halfLength = (length' xs) / 2
        fstHalf = take halfLength xs
        sndHalf = drop halfLength xs
Run Code Online (Sandbox Code Playgroud)

这是因为where它本身就是一个范围,所以绑定可以互相引用.

至于你的第二个片段,这完全不正确.甲let ? in语句是严格意义上的表达,而不能在一个结合上下文中使用where.

如果你在哪里使用let ? in,你会像这样使用它:

length' a = fromIntegral (length a)

isPalin1 xs =
    let halfLength = (length' xs) / 2
        fstHalf = take halfLength xs
        sndHalf = drop halfLength xs
    in  fstHalf == reverse sndHalf
Run Code Online (Sandbox Code Playgroud)


Nat*_*han 5

正如在评论中所提到的,对于isPalin1where属性的范围sndHalf,而不是fstHalf.我将重写这个isPalin1例子(语法上)的方式是这样的:

isPalin1 xs = fstHalf == reverse sndHalf
  where length' a = fromIntegral (length a)
        halfLength = (length' xs) / 2
        fstHalf = take halfLength xs
        sndHalf = drop halfLength xs
Run Code Online (Sandbox Code Playgroud)

这不会给你任何解析错误,并且范围都可以解决.但是,它不会编译,因为它的逻辑是关闭的.

问题是为什么你需要从整体?从查看代码的答案是,您正在尝试将列表拆分为一半,并且可能在尝试执行类似操作时更早出现编译错误(length xs) / 2.看起来你要做的就是将列表分成两半,但这对于具有给定逻辑的奇数长度列表来说根本不起作用.如果列表的长度11,应该fstHalfsndHalf是什么?(fromIntrgral (length xs)) / 2halfLength成为5.5,但你不能5.5从列表中获取元素,所以Haskell的类型系统会混淆

除此之外,您可以使用 (length xs) `div` 2整数除法,丢弃余数.如果xs是长度10,它将返回5.如果xs是长度11,它将返回5.我不想给你一个完整的解决方案,以防这是一个家庭作业问题,但只要想想你如何使用整数除法来使你的程序工作.考虑一下长度为偶数或奇数的列表将如何影响确定它们是否为回文的算法,并使您的代码考虑到这一点.

至于第二个错误你得到:原因是因为你有两个功能,fstHalf并且sndHalf是位于在inlet语句的条款,引起了解析错误.一般来说,我会建议避免嵌套whereif陈述,除非你绝对必须或你是一个受虐狂.一个你清理逻辑,尝试坚持where我在本文开头给出的示例语句的格式,它使事情变得更简单.

并且不要放弃Haskell,它会在你身上发展.:)