如何使用来自getLine的字符串映射?[Haskell]

时间:2011-11-10 04:48:00

标签: haskell map getline

我想读取一个String和toUpper所有字符。

import Data.Char

main = do 
    a <- getLine
    b <- getLine
    map toUpper a
    if (a == b) 
        then print 0
        else if (a < b) 
            then print (-1)
            else print 1

然后我得到了这个

Couldn't match expected type `IO a0' with actual type `[b0]'
    In the return type of a call of `map'
    In a stmt of a 'do' expression: map toUpper a
    In the expression:
      do { a <- getLine;
           b <- getLine;
           map toUpper a;
           if (a == b) then
               print 0
           else
               if (a < b) then print (- 1) else print 1 }

我可以使用来自getLine的String的地图吗? 或者有另一种方法来读取字符串和上述所有字符?

4 个答案:

答案 0 :(得分:7)

您没有分配&#34;结果&#34;你的map号召唤任何东西。这导致了您遇到的类型错误,它告诉您正在尝试返回一个字符串(map调用的结果),当它确实需要某种IO类型时。 / p>

直接修复看起来像这样:

import Data.Char

main = do 
    a <- getLine
    b <- getLine
    let c = map toUpper a
    if (c == b) 
        then print 0
        else if (c < b) 
            then print (-1)
            else print 1

如果你使用fmap,你可以toUpper所有字符并同时获取输入行(防止需要c)。

import Data.Char

main = do
    a <- fmap (map toUpper) getLine
    b <- getLine
    if a == b
        then print 0
        else if a < b
            then print (-1)
            else print 1

答案 1 :(得分:7)

其他人已经以最小的方式纠正了你的程序,但我想指出Haskell已经改进的C-ism:

if (a == b)
    then print 0
    else if (a < b)
        then print (-1)
        else print 1

是否曾经困扰过你数字被用于记录事物的比较?这肯定困扰着我。幸运的是,在Haskell中定义新数据类型非常便宜,我们一直都在这样做。在标准库中,有一个类型定义如下:

data Ordering = LT | EQ | GT

还有一个标准功能

compare :: Ord a => a -> a -> Ordering

那么为什么不使用这个美丽的Haskell工件?

main = do
    a <- getLine
    b <- getLine
    print (compare (map toUpper a) b)

答案 2 :(得分:4)

在Haskell中,将非monadic代码与monadic代码分开是一种很好的做法。

最小的改进是将print向外移动:

print $ if (a == c) 
    then 0
    else if (a < b) 
        then (-1)
        else 1

至于惯用解决方案,考虑在一个单独的函数中分离所有非monadic代码(比较和大写)。

此外,如果您在代码中看到elsif,请考虑警卫:

c_compare a c
    | a == c = 0
    | a < c = -1
    | otherwise = 1

案例实施也是可能的:

c_compare a c = case (compare a c) of
    LT -> -1
    EQ -> 0
    GT -> 1

答案 3 :(得分:2)

请记住,Haskell中的所有内容都是不可变的,因此调用map toUpper a实际上并不会修改a。如果您想保存该结果,则必须将其绑定到let子句中的变量。因此,您可能希望将代码更改为以下内容:

import Data.Char

main = do 
    a <- getLine
    b <- getLine
    let c = map toUpper a
    if (a == c) 
        then print 0
        else if (a < b) 
            then print (-1)
            else print 1