Reputation: 19664
I have three examples below. I am trying to understand why in the first case, I can assign the variable, but not print it. In the second, if I assign the whole thing as a string, I can print it later just fine. But in the third, if I do the compute and then try to print, this fails:
{-# LANGUAGE DeriveGeneric, OverloadedStrings, RankNTypes, KindSignatures, FlexibleContexts, AllowAmbiguousTypes #-}
:ext OverloadedStrings
import Data.Text as T
import Data.Text.IO as T
-- This works
mm1 x = do
T.putStrLn "Testing m1"
let m = T.pack $ show x
y = x * 2
T.putStrLn "Here is m"
T.putStrLn m
T.putStrLn "y has been assigned successfully, but not printed."
mm1 10
-- This also works
mm2 x = do
T.putStrLn "Testing m2"
let m = T.pack $ show x
y = T.pack $ show $ x * 2
T.putStrLn "Here is m"
T.putStrLn m
T.putStrLn "Here is y"
T.putStrLn y -- this prints fine
mm2 10
-- But This does not work
mm3 x = do
T.putStrLn "Testing m3"
let m = T.pack $ show x
y = x * 2
T.putStrLn "Here is m"
T.putStrLn m
T.putStrLn "y has been assigned cannot be printed:"
T.putStrLn T.pack $ show y
mm3 10
My error is:
<interactive>:8:9: error:
• Couldn't match expected type ‘String -> IO b’ with actual type ‘IO ()’
• The first argument of ($) takes one argument,
but its type ‘IO ()’ has none
In a stmt of a 'do' block: T.putStrLn pack $ show y
In the expression:
do T.putStrLn "Testing m3"
let m = pack $ show x
y = x * 2
T.putStrLn "Here is m"
T.putStrLn m
....
• Relevant bindings include mm3 :: a -> IO b (bound at <interactive>:1:1)
<interactive>:8:20: error:
• Couldn't match expected type ‘Text’ with actual type ‘String -> Text’
• Probable cause: ‘pack’ is applied to too few arguments
In the first argument of ‘T.putStrLn’, namely ‘pack’
In the expression: T.putStrLn pack
In a stmt of a 'do' block: T.putStrLn pack $ show y
I don't understand what this error is telling me.
Specifically, if
let
y = T.pack $ show $ x * 2
T.putStrLn y -- this prints fine
works. Why does:
let
y = x * 2
T.putStrLn T.pack $ show y
fail? These should be exactly identical, right?
Upvotes: 0
Views: 49
Reputation: 64740
No they are not identical.
The first one, inlined, parses as:
T.putStrLn (T.pack (show (x * 2)))
The second one parses as:
(T.putStrLn T.pack) (show (x * 2))
You can't putStrLn of the pack
function and then apply that result, as a function, to the input show y
. You probably wanted:
T.putStrLn $ T.pack $ show (x * 2)
or
T.putStrLn (T.pack (show (x * 2)))
EDIT: Reading the error message, this is what it's trying to help you understand:
T.putStrLn T.pack $ show y
^
|
Couldn't match expected type ‘Text’ with actual type ‘String -> Text’
The value T.pack
is of type String -> Text
but the type checker knows, based on T.putStrLn
, this value should be type Text
if things are to work.
T.putStrLn T.pack $ show y
|
Couldn't match expected type ‘String -> IO b’ with actual type ‘IO ()’
• The first argument of ($) takes one argument,
but its type ‘IO ()’ has none
If the first argument to $
, T.putStrLn T.pack
, were to type check then the result is dictated by the result of T.putStrLn
which is IO ()
. However, the first argument of $
must "take one argument" (be type a -> b
) and IO ()
clearly does not.
Upvotes: 7