Function Can';t将类型与head和+匹配+;

Function Can';t将类型与head和+匹配+;,function,haskell,types,Function,Haskell,Types,我是Haskell(和函数式编程)的完全初学者。我在尝试一段非常简单的代码时遇到了这个问题: Ciphers.hs:24:25: Couldn't match expected type ‘Bool’ with actual type ‘[Char]’ In the expression: sChars ++ (head c) 及 这是我试图执行的代码: --Datatype for a cipher type Cipher = String validateCipher :

我是Haskell(和函数式编程)的完全初学者。我在尝试一段非常简单的代码时遇到了这个问题:

Ciphers.hs:24:25:
    Couldn't match expected type ‘Bool’ with actual type ‘[Char]’
    In the expression: sChars ++ (head c)

这是我试图执行的代码:

--Datatype for a cipher
type Cipher = String

validateCipher :: Cipher -> Bool
validateCipher ciph = 
    if((length ciph) /= 26)then 
        False
    else if(let savedChars = "" in vCiph ciph savedChars)then
        True
    else
        False

vCiph :: Cipher -> String -> Bool
vCiph c sChars = 
    if(elem (head c) sChars)then
        False
    else if(length c == 0)then 
        True
    else
        sChars ++ (head c)
        vCiph (tail c) sChars
所以,实际上是最后两行造成了问题,我不知道为什么。老实说,我甚至不知道为什么预期的类型在第一个中是bool,为什么编译器的列号与记事本++不匹配,或者是否允许我在else语句之后有两行代码。

首先,有一种“超级简单”的方法

import Data.List

type Cipher = String

validateCipher :: Cipher -> Bool
validateCipher c = sort c == ['a'..'z']
然后,您尝试执行的操作有一个修复程序:

type Cipher = String

validateCipher :: Cipher -> Bool
validateCipher ciph = length ciph == 26 && vCiph ciph ""

vCiph :: Cipher -> String -> Bool
vCiph "" _ = True
vCiph (c:cs) prev
  | elem c prev  = False
  | otherwise    = vCiph cs (c:prev)
我在您的代码中注意到以下几点:

  • 代码检查
    头部c
    是否在
    sChars
    中,然后检查
    c
    是否为空。但是如果
    c
    是空的,那么就太晚了,因为
    头c
    抛出了一个异常

  • 代码
    sChars++(头c)
    不会修改
    sChars
    。它会创建一个新列表

  • 代码
    sChars++(头c)
    是一个类型错误,因为
    头c
    是一个
    Char
    ++
    要求两边都是
    [Char]

新版本通过模式匹配完成了一些事情:模式
(c:cs)
为您将参数拆分为head和tail,因此您不必显式地调用
head
tail
。模式
将匹配空字符串,因此您不必测试
长度c==0

下面是一个样式修正,解决了您对将
密码
变成
字符串
的担忧:

newtype Cipher = Cipher String

validateCipher :: Cipher -> Bool
validateCipher (Cipher ciph) = length ciph == 26 && vCiph ciph ""
  where
    vCiph :: String -> String -> Bool
    vCiph "" _ = True
    vCiph (c:cs) prev
      | elem c prev  = False
      | otherwise    = vCiph cs (c:prev)
使用
newtype
而不是
type
可以使
Cipher
就类型系统而言不再是
String
。把它想象成一个盒子,里面有一根绳子。它几乎与
data Cipher=Cipher String
相同,除了边缘情况

vCiph
作为
validateCipher
的一部分,可以清楚地表明
vCiph
与从其他函数调用无关。

首先,有一种“超级简单”的方法

import Data.List

type Cipher = String

validateCipher :: Cipher -> Bool
validateCipher c = sort c == ['a'..'z']
然后,您尝试执行的操作有一个修复程序:

type Cipher = String

validateCipher :: Cipher -> Bool
validateCipher ciph = length ciph == 26 && vCiph ciph ""

vCiph :: Cipher -> String -> Bool
vCiph "" _ = True
vCiph (c:cs) prev
  | elem c prev  = False
  | otherwise    = vCiph cs (c:prev)
我在您的代码中注意到以下几点:

  • 代码检查
    头部c
    是否在
    sChars
    中,然后检查
    c
    是否为空。但是如果
    c
    是空的,那么就太晚了,因为
    头c
    抛出了一个异常

  • 代码
    sChars++(头c)
    不会修改
    sChars
    。它会创建一个新列表

  • 代码
    sChars++(头c)
    是一个类型错误,因为
    头c
    是一个
    Char
    ++
    要求两边都是
    [Char]

新版本通过模式匹配完成了一些事情:模式
(c:cs)
为您将参数拆分为head和tail,因此您不必显式地调用
head
tail
。模式
将匹配空字符串,因此您不必测试
长度c==0

下面是一个样式修正,解决了您对将
密码
变成
字符串
的担忧:

newtype Cipher = Cipher String

validateCipher :: Cipher -> Bool
validateCipher (Cipher ciph) = length ciph == 26 && vCiph ciph ""
  where
    vCiph :: String -> String -> Bool
    vCiph "" _ = True
    vCiph (c:cs) prev
      | elem c prev  = False
      | otherwise    = vCiph cs (c:prev)
使用
newtype
而不是
type
可以使
Cipher
就类型系统而言不再是
String
。把它想象成一个盒子,里面有一根绳子。它几乎与
data Cipher=Cipher String
相同,除了边缘情况


vCiph
作为
validateCipher
的一部分,可以清楚地表明
vCiph
与从其他函数调用没有任何关系。

试图弄清楚sChars++(头c)vCiph(尾c)sChars的含义。这是一个单一的表达,换行符没有任何意义。哦,真的吗?我真的是认真的,当我说我是一个完全的哈斯凯尔·努伯时,我希望断线会把它分成两个陈述,而不是一个陈述;(和其他语言一样)。这些行的作用是将第一个字符添加到保存的字符列表中,然后递归,关键是检查密码是否只包含字母表中的每个字母中的一个。哦,你完全正确,在Haskell中,换行符会将语句分开。您还可以使用显式的
如有必要。但是,您没有编写任何语句——您编写的是纯函数。如果您告诉我们代码应该做什么,我们可能会对此有所帮助。仅仅通过查看代码就很难猜出代码应该做什么,这很公平。该代码旨在定义一个密码类型(功能上与字符串相同,这不是我的选择),然后验证包含字母表中每个字母的密码检查一次且仅一次。我首先检查它的长度为26,然后运行递归函数(vCiph),该函数用于检查密码中的第一个字母是否已存储在数组(savedChars)中。如果有,则密码无效(包含多个相同的字母),如果没有,则将其添加到列表中,并使用尾部递归,直到密码为空或错误,试图找出sChars++(head c)vCiph(tail c)sChars
的含义。这是一个单一的表达,换行符没有任何意义。哦,真的吗?我真的是认真的,当我说我是一个完全的哈斯凯尔·努伯时,我希望断线会把它分成两个陈述,而不是一个陈述;(和其他语言一样)。这些行的作用是将第一个字符添加到保存的字符列表中,然后递归,关键是检查密码是否只包含字母表中的每个字母中的一个。哦,你完全正确,在Haskell中,换行符会将语句分开。你可以