2010-06-22 61 views
1

我有一个模糊的类型变量在下面的“试验”的定义错误,我想知道是否有任何可以做到这种情况的工作?我只想处理实例而不是明确的数据类型(例如下面包含的MO1,MO2)。使用haskell读取和类型类 - 模糊类型变量错误

module Tc102 where 

class (Show a, Read a) => MyObj a where 
    alpha :: a->String 
    beta :: a->Int 

data MO1 = MO1 { a1 :: String, b1 :: Int } deriving (Show,Read) 
data MO2 = MO2 { a2 :: String, b2 :: Int } deriving (Show,Read) 

instance MyObj MO1 where 
    alpha = a1 
    beta = b1 

instance MyObj MO2 where 
    alpha = a2 
    beta = b2 


a = MO1 "a" 3 
b = MO2 "b" 4 

test :: MyObj a => a->String 
test = alpha 


showMe :: (MyObj a)=> a -> String 
showMe = show 

readMe :: (MyObj a) => String -> a 
readMe = read 

trial :: MyObj a => a -> String 
trial = test . readMe . showMe 

在此先感谢所有!但我担心我可能需要去将老ADT转换为“最新版本的辅助功能......

西蒙

编辑为了澄清,想象一下,我第一次展示给一个文件,然后稍后重新加载对象。然后,我具备的功能更像是

trial :: String -> Int 
trial s = beta x 
    where x = readMe s 

回答

0

您无法从运行时文件读取编译时类型。您应该明确实现运行时类型变化的值。

作为例子:

data AnyMyObj = forall a . MyObj a => AnyMyObj a 

test :: AnyMyObj -> String 
test (AnyMyObj x) = alpha x 

showMe :: AnyMyObj -> String 
showMe (AnyMyObj x) = show x 

readMe :: String -> AnyMyObj 
readMe s = AnyMyObj (read s :: MO1) -- maybe something more complicated 

trial :: AnyMyObj -> String 
trial = test . readMe . showMe 
+0

有点更多的type-foo,得到了应该工作的东西。谢谢! – 2010-06-22 06:32:27

1

你得到的错误,因为编译器不知道具体是什么类型readMe应该返回,因为所有test要求是,它是MyObj一个实例。它可能是MO1MO2或完全其他东西,并且readMe可能会返回任何这些。

假设你想readMe . showMe表现得像id和输出作为输入同一类型,快速和肮脏的方法是定义,不只是一个函数,并给它这相当于输入和输出类型签名类型:

trial :: MyObj a => a -> String 
trial = test . readShowMe 
    where readShowMe :: MyObj a => a -> a 
      readShowMe = readMe . showMe 

现在编译器可以找出什么具体类型给test作为输入。

+0

啊,难道你不喜欢它,当例子出错时,请检查原始文章的澄清! :) 虽然我仍然相信你的评论的第一部分仍然是问题。这是一个耻辱,给定typeclass信息和字符串格式,运行时无法确定obj是MO1等etc ... – 2010-06-22 03:26:06

0

有花哨的技巧,这一点,最终的答案确实是读入某种存在。想了解一个非常强大/通用的方法,请参阅Oleg的Typed-tagless最终讲义:http://okmij.org/ftp/tagless-final/course/#type-checking

但是这对于像你这样的例子来说是严重的矫枉过正 - 当你拥有树结构时,特别是当你拥有代表lambda术语的树结构时,技巧通常会进入。

为了您的目的,上面的ony的例子大致是正确的。

但请记住,即使您可以创建MyObj的新实例,您的读取功能也只能读取固定的Universe,至少不需要高级别的骇客。

所以这是一个问题,我会问你是否想要一个类型类型开始,或只是更多的构造函数在一个单一的ADT。

data MyObj = MO1 { a1 :: String, b1 :: Int } 
      | MO2 { a2 :: String, b2 :: Int } deriving (Show,Read) 

...例如。