首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于haskell、类型定义和保护的练习

关于haskell、类型定义和保护的练习
EN

Stack Overflow用户
提问于 2010-01-13 21:58:38
回答 4查看 951关注 0票数 4

第一个问题:

定义一个使用分隔符值将列表连接在一起的函数。

类型定义应该是这样的:

代码语言:javascript
复制
intersperse :: a -> [[a]] -> [a]

分隔符应该出现在列表的元素之间,但不应该紧跟在最后一个元素之后。

您的函数应如下所示:

代码语言:javascript
复制
ghci> :load Intersperse
[1 of 1] Compiling Main             ( Intersperse.hs, interpreted )
Ok, modules loaded: Main.
ghci> intersperse ',' []
""
ghci> intersperse ',' ["foo"]
"foo"
ghci> intersperse ',' ["foo","bar","baz","quux"]
"foo,bar,baz,quux"

过了一段时间,我设法解决了这个问题:

代码语言:javascript
复制
intersperse myChar lists
    | lists == []          = ""  
    | otherwise            = attach myChar lists
        where   attach myChar (x:[]) = x 
                attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs 

但是,如您所见,它没有类型定义。

如果我把类型定义放在函数上面,我会得到一个错误。为什么?

第二个问题:

在我得到这个解决方案之前,我想在保安列表中添加另一个保安。这个quard应该在第一个守卫之后。我想检查列表变量中是否只有一个列表,所以我只返回列表变量。但我不能做这样的守卫(再说一次,错误来了:-):

代码语言:javascript
复制
| lists == (x:[]) = lists

而且这也不起作用:

代码语言:javascript
复制
| lists == (_:[]) = lists

为什么?:-)。

在这之后,我试着做其他的守卫:

代码语言:javascript
复制
| length lists == 1    = lists

但它也引发了一个错误。

(顺便说一下,我不需要这些保护,因为我发现"where“关键字后的第一个模式正是我想要的。

这是我想说的模式:

代码语言:javascript
复制
attach myChar (x:[]) = x

但是,我仍然想知道为什么我尝试的quards不起作用。另外,幸运的是,我找到了这个解决方案,我不认为每次我都会注意到这样的事情:-)

非常感谢:-)。

附注:本练习来自real world haskell一书。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-01-13 22:12:16

  1. ""的类型是[Char],但是你的类型签名说intersperse返回一个[a],而a依赖于输入类型,所以类型不匹配。
  2. 我不认为你可以在内部进行模式匹配。

为了这个守卫

|长度列表== 1=列表

lists的类型为[[a]],但您应该返回一个[a]。也就是说,如果lists["foo"],则需要返回"foo"。您不希望返回["foo"].

票数 3
EN

Stack Overflow用户

发布于 2010-01-13 22:13:57

问题是你的函数不是泛化的,它只适用于字符串(字符列表)。如果您将第二行更改为

代码语言:javascript
复制
lists == []          = []

您将得到您想要的东西,尽管由于等于运算符而依赖于Eq类型类。它甚至适用于字符串,因为所有的字符串也是列表,但并不是所有的列表都是字符串。

顺便说一下,您可以通过使用模式匹配进一步泛化您的函数:

代码语言:javascript
复制
intersperse myChar lists = case lists of
    []      -> []
    lists   -> attach myChar lists
    where   attach myChar (x:[]) = x 
            attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs 

或者,更地道地说:

代码语言:javascript
复制
intersperse _ [] = []
intersperse x xs = attach x xs
    where   attach myChar (x:[]) = x 
            attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs

并摆脱了内部函数:

代码语言:javascript
复制
intersperse _ [] = []
intersperse _ (xs:[]) = xs
intersperse x (xs:xss) = (xs ++ x:intersperse x xss)

关于第二个问题,您在卫士中使用的equals运算符需要两端都有值。你不能和它进行模式匹配。也许您正在寻找的是类似于这里的第二次改进。

票数 2
EN

Stack Overflow用户

发布于 2010-01-13 22:36:27

这会引发一个错误。

为什么?它和你做的一样,除了你用case of写的。

代码语言:javascript
复制
intersperse :: a -> [[a]] -> [a]
intersperse myChar lists
    | lists == []          = []  
    | otherwise            = attach myChar lists
        where   attach myChar (x:[]) = x 
                attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs

这不会引发错误(这是您所建议的):

代码语言:javascript
复制
intersperse :: a -> [[a]] -> [a]
intersperse myChar lists = case lists of
    []      -> []
    lists   -> attach myChar lists
    where   attach myChar (x:[]) = x 
            attach myChar (x:xs) = x ++ (myChar : []) ++ attach myChar xs

但是在我的示例中(这里的第一个函数),我按照您的建议更改了防护,但仍然得到一个错误。

为什么会这样呢?

非常感谢。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2057093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档