无法放置刚分配的内容

时间:2019-04-25 16:00:41

标签: haskell

我下面有三个例子。我试图理解为什么在第一种情况下,我可以分配变量,但不能打印它。在第二个中,如果我将整个内容分配为字符串,则以后可以打印它。但是在第三种情况下,如果我先进行计算然后尝试打印,则会失败:

{-# 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

我的错误是:

<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

我不明白这个错误告诉我什么。

具体来说,如果

    let
        y = T.pack $ show $ x * 2
    T.putStrLn y  -- this prints fine

有效。为什么:

    let
        y = x * 2
    T.putStrLn T.pack $ show y

失败?这些应该完全相同,对吧?

1 个答案:

答案 0 :(得分:8)

不,它们并不相同。

第一个内联解析为:

T.putStrLn (T.pack (show (x * 2)))

第二个解析为:

(T.putStrLn T.pack) (show (x * 2))

您不能将pack函数的StrLn放入函数show y并将其结果作为函数应用到输入T.putStrLn $ T.pack $ show (x * 2) 。您可能想要:

T.putStrLn (T.pack (show (x * 2)))

T.putStrLn T.pack $ show y
            ^
             |
     Couldn't match expected type ‘Text’ with actual type ‘String -> Text’

编辑:阅读错误消息,这是它试图帮助您了解的内容:

T.pack

String -> Text的类型为T.putStrLn,但是类型检查器基于Text知道,如果工作正常,则该值应该为 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

$

如果T.putStrLn T.pack的第一个参数T.putStrLn键入check,则结果由IO ()的结果$决定。但是,a -> b的第一个参数必须“采用一个参数”(输入IO ()),而{ "message": "Unauthenticated." } 显然不需要。