0

The minimal code:

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

main = do
   return twice ++ "H"

The errors generated:

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"
  |                    ^^^

How would I logically fix this issue myself? Clearly it's something I'm doing wrong. Am I missing a preamble that every example should have?

MathCrackExchange
  • 595
  • 1
  • 6
  • 25
  • 3
    What are you actually trying to do? The fundamental problem is that `twice ++ "H"` is trying to append a string to a function, which doesn't really make any sense at all. I suspect you might have meant `twice (++ "H")` which is applying the function `twice` to a function. That would "work" in that it would compile, but then you would have a `main` of type `IO (String -> String)` which doesn't really make much sense either. (It would certainly have no observable effect when ran.) Do you want to just define a function `g = twice (++ "H")` and play around with it? If so, just do that. – Robin Zigmond Nov 19 '19 at 22:04
  • @RobinZigmond the general problem is. I'm looking at examples from: http://learnyouahaskell.com/higher-order-functions and they're not working at least not as explicitly written. – MathCrackExchange Nov 19 '19 at 22:10
  • 1
    Thank you for the link (I have been through LYAH several times, although not for a while - it was my entry point into Haskell - and I dind't recognise this example). It looks like you're trying to experiment with the function called `applyTwice` in that chapter. Yet your attempt looks nothing like the examples in the book, so I advise you to look closer at those (for one thing, in those examples there is no `main` in sight - as far as I remember most examples in LYAH are designed to be ran in GHCi after loading the appropriate function definitions from a file). – Robin Zigmond Nov 19 '19 at 22:50

1 Answers1

3

As RobinZigmond mentions in the comments, you can’t write twice ++ "H". This means, ‘take the function twice, and append the string "H" to it’. This is clearly impossible, since ++ can only append strings and lists together. I suspect that what you meant was twice (++ "H"). This takes the function (++ "H"), which appends "H" to the end of its argument, and runs it twice.

But even if you do this, there is still a problem. Take a look at the program which is created if you do this:

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

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

Even though this program compiles, it doesn’t do anything! You have set twice (++ "H")) as the return value of main, but the return value of main is always ignored. In order to produce output, you need to use putStrLn instead of return:

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

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

But this program doesn’t work either! twice (++ "H") is a function, which cannot be printed. This function must be applied to a value in order to produce a result:

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

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

This program should finally work, giving an output of Starting valueHH when it is run.

bradrn
  • 8,337
  • 2
  • 22
  • 51