Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typeOf on return type

Tags:

haskell

I'm extending an answer to Haskell setting record field based on field name string? to add a generic getField. I'm using gmapQi, and I want to generate an error if the type of the encountered sub-element does not match the expected type. I want the error message to include the name of the type that was encountered, as well as the name of the type expected. The function looks like this:

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Generics
import Prelude hiding (catch)
import Control.Exception

getField :: (Data r, Typeable v) => Int -> r -> v
getField i r = gmapQi i (e `extQ` id) r
  where
    e x = error $ "Type mismatch: field " ++ (show i) ++
                  " :: " ++ (show . typeOf $ x) ++
                  ", not " ++ (show . typeOf $ "???")

---------------------------------------------------------------------------------

data Foo = Foo Int String
  deriving(Data, Typeable)

handleErr (ErrorCall msg) = putStrLn $ "Error -- " ++ msg

main = do
  let r = Foo 10 "Hello"
  catch (print (getField 0 r :: Int))    handleErr
  catch (print (getField 0 r :: String)) handleErr
  catch (print (getField 1 r :: Int))    handleErr
  catch (print (getField 1 r :: String)) handleErr

The problem is, I don't know what to put in place of "???" to get the return type of the getField function (i.e. how to reify v from the type signature).

like image 993
pat Avatar asked Dec 30 '11 20:12

pat


People also ask

What does typeof () return in C?

In other languages, such as C# or D and, to some degree, in C (as part of nonstandard extensions and proposed standard revisions), the typeof operator returns the static type of the operand. That is, it evaluates to the declared type at that instant in the program, irrespective of its original form.

What is the use typeof () in R?

typeof() function in R Language is used to return the types of data used as the arguments.

Does typeof work in TypeScript?

typeof is used to differentiate between the different types in TypeScript. By the use of typeof we can differentiate between number, string, symbol, Boolean, etc. typeof can be used with any type in TypeScript, by the use of it we can re-use the code by passing any parameter type.

Why does typeof null return object?

The reasoning behind this is that null , in contrast with undefined , was (and still is) often used where objects appear. In other words, null is often used to signify an empty reference to an object. When Brendan Eich created JavaScript, he followed the same paradigm, and it made sense (arguably) to return "object" .


2 Answers

typeOf never evaluates its argument, so you can use any expression as long as it's of the correct type. In this case, the type of the result is the same as the return type of e, so you can just use e x.

getField :: (Data r, Typeable v) => Int -> r -> v
getField i r = gmapQi i (e `extQ` id) r
  where
    e x = error $ "Type mismatch: field " ++ (show i) ++
                  " :: " ++ (show . typeOf $ x) ++
                  ", not " ++ (show . typeOf $ e x)

This gives the expected output when run:

10
"Error -- Type mismatch: field 0 :: Int, not [Char]
Error -- Type mismatch: field 1 :: [Char], not Int
"Hello"
like image 132
hammar Avatar answered Oct 21 '22 11:10

hammar


You can use (show . typeOf $ (undefined :: v)) if you add forall r v. to the start of your type signatures and turn on the ScopedTypeVariables extension.

It'll be possible to achieve without that — usually it involves dummy helper functions to coerce the types into the form you want — but it will be very ugly and I'm not sure how.

like image 43
ehird Avatar answered Oct 21 '22 11:10

ehird