在Haskell中基本的“两次申请”问候世界中类型不匹配

时间:2019-11-19 22:01:30

标签: function haskell visual-studio-code first-class-functions

最小代码:

twice :: (a -> a) -> a -> a
twice f = f . f

main = do
   return twice ++ "H"

产生的错误:

stack runhaskell "c:\Users\FruitfulApproach\Desktop\Haskell\test.hs"

C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1: error:
    * Couldn't match expected type `IO t0'
                  with actual type `[(a0 -> a0) -> a0 -> a0]'
    * In the expression: main
      When checking the type of the IO action `main'
  |
5 | main = do
  | ^

C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:6:20: error:
    * Couldn't match type `Char' with `(a -> a) -> a -> a'
      Expected type: [(a -> a) -> a -> a]
        Actual type: [Char]
    * In the second argument of `(++)', namely `"H"'
      In a stmt of a 'do' block: return twice ++ "H"
      In the expression: do return twice ++ "H"
    * Relevant bindings include
        main :: [(a -> a) -> a -> a]
          (bound at C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1)
  |
6 |    return twice ++ "H"
  |                    ^^^

我如何逻辑上自己解决此问题?显然这是我做错的事情。我是否错过了每个示例都应有的序言?

1 个答案:

答案 0 :(得分:3)

正如罗宾·齐格蒙德(RobinZigmond)在评论中提到的那样,您不能写twice ++ "H"。这就是说,“采用功能twice,并将字符串"H"附加到其上”。这显然是不可能的,因为++只能将字符串和列表附加在一起。我怀疑您的意思是twice (++ "H")。这将使用函数(++ "H"),该函数将"H"附加到其参数的末尾,并运行两次。

但是即使执行此操作,仍然存在问题。查看执行以下操作创建的程序:

twice :: (a -> a) -> a -> a
twice f = f . f

main = do
   return (twice (++ "H"))

即使该程序可以编译,它也无济于事!您已将twice (++ "H"))设置为main的返回值,但始终会忽略main的返回值。为了产生输出,您需要使用putStrLn而不是return

twice :: (a -> a) -> a -> a
twice f = f . f

main = do
   putStrLn (twice (++ "H"))

但是该程序也不起作用! twice (++ "H")是无法打印的功能。必须将此函数应用于一个值才能产生结果:

twice :: (a -> a) -> a -> a
twice f = f . f

main = do
   putStrLn (twice (++ "H") "Starting value")

该程序最终应该可以运行,运行时输出为Starting valueHH