Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit type conversion?

Tags:

types

haskell

This is an example function:

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)

I'm struggling to understand the exact purpose of CHA.ByteString in this line:

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

Is this explicitly stating the type must be CHA.ByteString? Or does it serve another role?

like image 573
Babra Cunningham Avatar asked Dec 23 '22 23:12

Babra Cunningham


1 Answers

Yes, this is just explicitly stating that the type must be CHA.ByteString. This does (by itself) not incur any sort of conversion, it's just a hint for the compiler (and/or the reader) that res must have this type.

These kinds of local annotations are needed when a value is both produced from a function with polymorphic result, and only consumed by functions with polymorphic argument. A simple example:

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

Here, toEnum converts an integer to a arbitrary enumerable type – could for instance be Char. Whatever type you'd choose, fromEnum would be able to convert it back... trouble is, there is no way to decide which type should be used for the intermediate result!

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

For some simple number classes, Haskell has defaults, so e.g. fromIntegral . round will automatically use Integer. But there are no defaults for types like ByteString, so with a polymorphic-result function like responseBody, you either need to pass the result to a monomorphic function that can only accept CHA.ByteString, or you need to add an explicit annotation that this should be the type.

like image 196
leftaroundabout Avatar answered Dec 29 '22 13:12

leftaroundabout