Haskell格式问题

Haskell格式问题,haskell,format,Haskell,Format,我是haskell编程的初学者,经常会出错 xxx.hs:30:1: parse error on input `xxx' 通常会有一点玩弄解决方案的格式。这是相同的代码,看起来也一样,但在玩过之后,错误就消失了 目前我已经知道了错误 LookupAll.hs:30:1: parse error on input `lookupAll' 在该代码之后: lookupOne :: Int -> [(Int,a)] -> [a] lookupOne _ [] = [] lookupO

我是haskell编程的初学者,经常会出错

xxx.hs:30:1: parse error on input `xxx'
通常会有一点玩弄解决方案的格式。这是相同的代码,看起来也一样,但在玩过之后,错误就消失了

目前我已经知道了错误

LookupAll.hs:30:1: parse error on input `lookupAll'
在该代码之后:

lookupOne :: Int -> [(Int,a)] -> [a]
lookupOne _ [] = []
lookupOne x list = 
    if fst(head list) == x then snd(head list) : []
    lookupOne x (tail list)
-- | Given a list of keys and a list of pairs of key and value
--   'lookupAll' looks up the list of associated values for each key
--   and concatenates the results. 

lookupAll :: [Int] -> [(Int,a)] -> [a]
lookupAll [] _ = []
lookupAll _ [] = []
lookupAll xs list = lookupOne h list ++ lookupAll t list    
    where
        h = head xs
        t = tail xs
但在我看来,我做的一切都是对的。没有标签之类的东西。始终为4个空格。这个问题有一个通用的解决方案吗?我现在正在使用记事本+


谢谢

问题不在于
lookupAll
,而在于前两行代码

if fst (head list) == x then snd (head list) : []
lookupOne x (tail list)
此if语句中没有包含
else
。我猜你的意思是

if fst (head list) == x then snd (head list) : []
else lookupOne x (tail list)
我个人更愿意将其格式化为

if fst (head list) == x
    then snd (head list) : []
    else lookupOne x (tail list)
但这是品味的问题


如果您想积累一个符合条件的值列表,有几种方法。到目前为止,最简单的方法是使用
过滤器
,但也可以使用显式递归。要使用
过滤器
,您可以将函数编写为

lookupOne x list
    = map snd                         -- Return only the values from the assoc list
    $ filter (\y -> fst y == x) list  -- Find each pair whose first element equals x
如果您想使用递归,可以将其编写为

lookupOne _ [] = []                  -- The base case pattern
lookupOne x (y:ys) =                 -- Pattern match with (:), don't have to use head and tail
    if fst y == x                    -- Check if the key and lookup value match
        then snd y : lookupOne x ys  -- If so, prepend it onto the result of looking up the rest of the list
        else         lookupOne x ys  -- Otherwise, just return the result of looking up the rest of the list
这两者是等价的。实际上,您可以将
过滤器
实现为

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list
map
as

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list

希望您可以发现<代码>过滤器> />代码>代码> LoopUnn>代码>,并使用<代码> MAP>代码>考虑<代码> f==SND ,因此,在代码< > LoopUnON/CODE>的显式递归版本中,合并了两个模式:<代码> MAP>代码>和<代码>过滤器>代码>。你可以把这个组合模式推广到一个高阶函数中

mapFilter :: (a -> b) -> (a -> Bool) -> [a] -> [b]
mapFilter f cond [] = []
mapFilter f cond (x:xs) =
    if cond x
        then f x : mapFilter f cond xs
        else     : mapFilter f cond xs
您可以使用它来实现
lookupOne
as

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list
或者更简单地说

lookupOne x = mapFilter snd ((== x) . fst)

问题不在于
lookupAll
,而在于前两行代码

if fst (head list) == x then snd (head list) : []
lookupOne x (tail list)
此if语句中没有包含
else
。我猜你的意思是

if fst (head list) == x then snd (head list) : []
else lookupOne x (tail list)
我个人更愿意将其格式化为

if fst (head list) == x
    then snd (head list) : []
    else lookupOne x (tail list)
但这是品味的问题


如果您想积累一个符合条件的值列表,有几种方法。到目前为止,最简单的方法是使用
过滤器
,但也可以使用显式递归。要使用
过滤器
,您可以将函数编写为

lookupOne x list
    = map snd                         -- Return only the values from the assoc list
    $ filter (\y -> fst y == x) list  -- Find each pair whose first element equals x
如果您想使用递归,可以将其编写为

lookupOne _ [] = []                  -- The base case pattern
lookupOne x (y:ys) =                 -- Pattern match with (:), don't have to use head and tail
    if fst y == x                    -- Check if the key and lookup value match
        then snd y : lookupOne x ys  -- If so, prepend it onto the result of looking up the rest of the list
        else         lookupOne x ys  -- Otherwise, just return the result of looking up the rest of the list
这两者是等价的。实际上,您可以将
过滤器
实现为

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list
map
as

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list

希望您可以发现<代码>过滤器> />代码>代码> LoopUnn>代码>,并使用<代码> MAP>代码>考虑<代码> f==SND ,因此,在代码< > LoopUnON/CODE>的显式递归版本中,合并了两个模式:<代码> MAP>代码>和<代码>过滤器>代码>。你可以把这个组合模式推广到一个高阶函数中

mapFilter :: (a -> b) -> (a -> Bool) -> [a] -> [b]
mapFilter f cond [] = []
mapFilter f cond (x:xs) =
    if cond x
        then f x : mapFilter f cond xs
        else     : mapFilter f cond xs
您可以使用它来实现
lookupOne
as

filter cond [] = []
filter cond (x:xs) =
    if cond x
        then x : filter cond xs
        else     filter cond xs
map f [] = []
map f (x:xs) = f x : map f xs
lookupOne x list = mapFilter snd (\y -> fst y == x) list
或者更简单地说

lookupOne x = mapFilter snd ((== x) . fst)

我认为@bheklillr是对的-您缺少了一个

但是,您可以通过将
lookupOne
形成函数组合,而不是编写自己的新递归函数,来解决这个特定的格式问题

例如,您可以通过如下定义
lookupOne
来获得正确的行为:

lookupOne a = map snd . filter ((==) a . fst)

通过这种方式,更清楚的是,您首先过滤掉输入列表中元组的第一个元素与键匹配的元素,然后只提取每个元组的第二个元素。

我认为@bheklir是正确的-您缺少了一个

但是,您可以通过将
lookupOne
形成函数组合,而不是编写自己的新递归函数,来解决这个特定的格式问题

例如,您可以通过如下定义
lookupOne
来获得正确的行为:

lookupOne a = map snd . filter ((==) a . fst)

这样就更清楚了,您首先要过滤掉输入列表中元组的第一个元素与键匹配的元素,然后只提取每个元组的第二个元素。

您忘记了
else
子句不是Haskell中
if
表达式的可选部分。您忘记了
else
子句不是Haskell中
if
表达式的可选部分。首先,我使用了“else”,但这不是我想要的代码。因为问题不做它必须做的事情:D我需要它而不需要“else”。如果是xxx,那么xxx和than总是yyy。你知道我的意思吗?但你是对的。对于“else undefined”,编译代码不会出错。@fuuman是否要累积要返回的值列表?如果是这样的话,那就不是这样做的。在Haskell中,计算一个值(
snd(head list):[]
)是没有意义的,然后扔掉该值,再计算另一个值(
lookupOne x(tail list)
)。所有表达式都返回一个值,并且该值必须是静态类型。这就是代码应该做的:lookupAll[1,2][(1,“Koblenz”),(1,“Koblenz”)]~=[“Koblenz”,“Koblenz”],[1,1][(1,“Koblenz”)]~=[“Koblenz”,“Koblenz”],在查找之前的else中有:;##失败:lookupAll:1应为:[“Koblenz”,“Koblenz”]但是得到:[“科布伦茨”]。。。。在其他语言中,您只能在不需要其他语言的情况下编写。但是编译器给了我一个错误,所以我需要这里的else。所以我需要一个cmd,它不做任何我想做的事情。我没有遍历第一个值。我把它保存在列表中。之后,我重新启动了我的函数。感谢每次我带着我的代码问题来到这个网站时所付出的巨大努力。这个网站很棒!感谢所有的回答,特别是贝克利尔的所有解释!:-)首先,我用了“else”,但那不是我想要的代码。因为问题不做它必须做的事情:D我需要它而不需要“else”。如果是xxx,那么xxx和than总是yyy。你知道我的意思吗?但你是对的。用一个“else”