显式类型转换?

时间:2016-11-25 22:23:00

标签: haskell types

这是一个示例函数:

import qualified Data.ByteString.Lazy as LAZ
import qualified Data.ByteString.Lazy.Char8 as CHA
import Network.Wreq

makeRequest :: IO (Network.Wreq.Response LAZ.ByteString)
makeRequest = do 
   res <- get "http://www.example.com" 
   let resBody = res ^. responseBody :: CHA.ByteString
   --Do stuff....
   return (res)

我正努力在这一行中理解CHA.ByteString的确切目的:

let resBody = res ^. responseBody :: CHA.ByteString

这是明确说明类型必须是CHA.ByteString吗?或者它是否扮演另一个角色?

2 个答案:

答案 0 :(得分:6)

是的,这只是明确说明类型必须是CHA.ByteString。这(本身)会产生任何类型的转换,它只是res必须具有此类型的编译器(和/或读取器)的提示。

当从具有多态结果的函数生成值时,需要这些类型的本地注释,并且仅由具有多态参数的函数使用。一个简单的例子:

f :: Int -> Int
f = fromEnum . toEnum

这里,toEnum将整数转换为任意可枚举类型 - 例如可以是Char。无论你选择哪种类型,fromEnum都可以将它转换回来......麻烦的是,没有办法决定哪种类型应该用于中间结果!

No instance for (Enum a0) arising from a use of ‘fromEnum’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
  instance Integral a => Enum (GHC.Real.Ratio a)
    -- Defined in ‘GHC.Real’
  instance Enum Ordering -- Defined in ‘GHC.Enum’
  instance Enum Integer -- Defined in ‘GHC.Enum’
  ...plus 7 others
In the first argument of ‘(.)’, namely ‘fromEnum’
In the expression: fromEnum . toEnum
In an equation for ‘f’: f = fromEnum . toEnum

对于一些简单的数字类,Haskell有默认值,所以例如fromIntegral . round会自动使用Integer。但是像ByteString这样的类型没有默认值,所以对于像responseBody这样的多态结果函数,你需要将结果传递给 只能接受的单态函数CHA.ByteString,或者您需要添加一个明确的注释,它应该是类型。

答案 1 :(得分:4)

符号x :: T读取表达式x的类型为T

在存在类型类和更高排序类型的情况下,这可能是必要的,以使编译器能够键入检查程序。例如:

main = print . show . read $ "1234"

是不明确的,因为编译器无法知道要使用哪个重载的read函数。

此外,可以缩小编译器推断的类型。例如:

1 :: Int

最后,像这样的类型签名通常用于使程序更具可读性。