【问题标题】:typeOf on return typetypeOf 返回类型
【发布时间】:2011-12-30 20:36:45
【问题描述】:

我将答案扩展到Haskell setting record field based on field name string? 以添加通用getField。我正在使用gmapQi,如果遇到的子元素的类型与预期的类型不匹配,我想生成一个错误。我希望错误消息包含遇到的类型的名称以及预期类型的​​名称。函数如下所示:

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

问题是,我不知道用什么代替 "???" 来获取 getField 函数的返回类型(即如何从类型签名中具体化 v)。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    typeOf 从不计算它的参数,所以你可以使用任何表达式,只要它是正确的类型。在这种情况下,结果的类型与e的返回类型相同,所以你可以使用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)
    

    这会在运行时给出预期的输出:

    10
    "Error -- Type mismatch: field 0 :: Int, not [Char]
    Error -- Type mismatch: field 1 :: [Char], not Int
    "Hello"
    

    【讨论】:

      【解决方案2】:

      如果您将forall r v. 添加到类型签名的开头并打开ScopedTypeVariables 扩展,则可以使用(show . typeOf $ (undefined :: v))

      没有它也有可能实现——通常它涉及到将类型强制转换为你想要的形式的虚拟辅助函数——但它会非常难看,我不确定如何。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-18
        • 2022-07-21
        • 2012-09-21
        • 2015-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多