Haskell 如何打字
C#: Haskell? 在我看来,Haskell没有根类型的对象,这有点棘手Haskell 如何打字,haskell,casting,Haskell,Casting,C#: Haskell? 在我看来,Haskell没有根类型的对象,这有点棘手 编辑:我不关心转换为字符串。我想知道如何进行类型转换(例如,查看对象是客户还是订单。在Haskell中,所有允许转换为字符串的类型都实例化了提供 static int F(object x) { return x is string ? 1 : 2; } 所以你的整个代码只是 show :: Show a => a -> String 或 对于相同的泛型类型f::Show a=>a->String(
编辑:我不关心转换为字符串。我想知道如何进行类型转换(例如,查看对象是客户还是订单。在Haskell中,所有允许转换为字符串的类型都实例化了提供
static int F(object x)
{
return x is string ? 1 : 2;
}
所以你的整个代码只是
show :: Show a => a -> String
或
对于相同的泛型类型f::Show a=>a->String
(对于所有可转换为字符串的类型a
,获取此类型的值并返回字符串)
请注意,您不必像C#中那样进行显式的运行时类型检查,通用模板在编译时解析。您不需要多态根类型-像C#中那样的强制转换实际上有点复杂,并且违背了语言的概念。它不允许在类型之间进行任意强制转换,而是为某些类型定义了类型类n有意义的转换
请注意,兼容性是在编译时检查的:
f = show
在回答您编辑的问题时:
正如我之前所说,Haskell中不允许任意转换(没有非常不安全的代码)。由于Haskell不是面向对象的,因此不存在需要任何强制转换的继承关系。根本不存在需要运行时检查/强制转换的毫无意义的对象
值。要表达备选方案,您必须定义联合类型、类型类或使用或类型
在什么情况下,您遇到的对象是客户
或订单
?这种类型的值根本没有意义。请再次澄清
关于您的记录器示例:
您需要一个typeclass:
-- Working
f 1
f "Hallo"
f (1, 2)
f [1, 2, 3]
-- Not working
f (\x -> x + 1)
在C#中,不做演员可能更有效:
class Loggable a where
writeToLog :: a -> IO ()
在Haskell中有一个“show”类型类,任何实现该类型类的对象都可以调用show,因此不需要强制转换。如果希望对象既可以是客户,也可以是订单,那么您应该引入一个新的数据类型“Customer | Order”,以便每个对象都带有一个类型标记,表明它是什么
我不知道Haskell的语法,但在F#中应该是
return x == null ? null : x.ToString();
更一般地说,在Haskell中,如果您想执行固定的OO类型层次结构之类的操作(对于一组固定的高度相关的类型,在某些情况下可以将它们视为相同的类型),您可以使用上述联合类型。另一方面,对于跨各种不相关类型的常见操作(如ToString/Show)您可以使用Haskell类型的类。这是我以前尝试过的,我认为您做不到
哈斯克尔采取了非常不同的态度
方法。它从执行类型开始
使用类型检查器进行分析,以
在编译时理解你的程序
时间。严格检查类型
禁止类型转换,不允许
允许忽略类型错误。
因为类型是在编译时检查的
时间,没有逃避的余地
类型检查器,Haskell经常
描述为静态类型和
强类型
Dario是对的,通常在Haskell中,您希望创建一个类型类来分派某个对象的类型。也就是说,有一种类型安全的方法可以在Haskell中强制转换。这是通用编程库的一部分,允许您编写“有趣的”部分复杂嵌套数据类型的操作,而SYB填补了空白。大脑融合太棒了。以下是关于它的介绍
以下是演员阵容:
type CustOrOrd =
| Cust of Customer
| Ord of Order
let F (x:CustOrOrd) : int =
match x with
| Cust c -> 1
| Ord o -> 2
let thing1 = Cust someCustomer
let thing2 = Ord someOrder
// can call F on thing1 or thing2
铸造和是
/实例
在该功能的语言中是有意义的。您的问题可以用几种方式回答:
- Haskell没有子类型,因此
是
/实例
在Haskell中没有意义;只有显式转换。没有可扩展所有类型的对象
类型
- Haskell的类型类提供了特殊的多态性,并有助于为许多转换重载单个名称。例如(正如其他人所指出的)
show
是用于将任何类型转换为字符串的重载名称。类型类还可用于使某些转换(似乎)隐式
- 泛型库的作者使用类型类创建了一个安全强制转换函数(其他人也指出了这一点)
正如Dario所观察到的,最直接的方法是使用它,它涵盖了所有标准类型,尽管您需要通过“导出可键入的
”,或者为要涵盖的您自己的类型定义实现typeOf
。这不是标准的Haskell 98,但它从6.2.2开始就在ghc中
您的代码可以实现:
cast :: (Typeable a, Typeable b) => a -> Maybe b
ghci> (cast 'a') :: Maybe Char
Just 'a'
ghci> (cast 'a') :: Maybe Bool
Nothing
ghci> (cast True) :: Maybe Bool
Just True
stringtyperep::TypeRep
stringtyperep=somestring的类型
F::(可键入的'a)=>'a->整数
F x |(typeOf x==stringtyperep)=1
fx=2
一般来说,使用泛型编程可以更好地实现OO风格的类型反射,但这不是一个很好的例子
此外,typeclassTypeable
中的所有类型都可以“强制”到中。定义Object
您自己
如果您的用例非常简单,那么最好自己定义对象类型,因此:
stringtyperep :: TypeRep
stringtyperep = typeOf "somestring"
F :: (Typeable 'a) =>'a -> Integer
F x | (typeOf x == stringtyperep) = 1
F x = 2
显然,您必须为每个类型编写一个实例
声明,您可能希望在使用类型
的函数中用作对象。当您尝试为元组定义实例
时,这可能会变得棘手,因为在Haskell中,如果两个元组的元素数不相同,那么它们的类型就不同因此,您可能必须编写无限多的实例
声明,如下所示:
data Type = String | Integer | List | Bool
deriving (Eq, Show)
class Object a where
typeOf :: a -> Type
instance Object String where typeOf _ = String
instance Object Integer where typeOf _ = Integer
instance Object [a] where typeOf _ = List
instance Object Bool where typeOf _ = Bool
f :: (Object a, Num b) => a -> b
f x = if typeOf x == String then 1 else 2
使用Data.Typeable
如果您的使用变得更复杂,您可以尝试:
如果您愿意,您可以将(undefined::String)
替换为”
,以更容易理解的为准。将任意类型强制转换为
data Type = String | Integer | List | Bool
deriving (Eq, Show)
class Object a where
typeOf :: a -> Type
instance Object String where typeOf _ = String
instance Object Integer where typeOf _ = Integer
instance Object [a] where typeOf _ = List
instance Object Bool where typeOf _ = Bool
f :: (Object a, Num b) => a -> b
f x = if typeOf x == String then 1 else 2
data Type = String | Integer | List | Bool | Tuple
deriving (Eq, Show)
instance Object () where typeOf _ = Tuple
instance Object (a) where typeOf _ = Tuple
instance Object (a,b) where typeOf _ = Tuple
instance Object (a,b,c) where typeOf _ = Tuple
instance Object (a,b,c,d) where typeOf _ = Tuple
instance Object (a,b,c,d,e) where typeOf _ = Tuple
instance Object (a,b,c,d,e,f) where typeOf _ = Tuple
instance Object (a,b,c,d,e,f,g) where typeOf _ = Tuple
import Data.Typeable
f :: (Typeable a, Num b) => a -> b
f x = if typeOf x == typeOf (undefined::String) then 1 else 2