我有一个函数(a->a)
,它可以采用不同的类型,但有没有办法确定参数的数据类型是什么?
像
foo :: a -> a
foo a == int =..
foo a == char =..
有没有在haskell做这样的检查?
答案 0 :(得分:6)
没有
改为使用数据类型:
data MyType = MyInt Int | MyChar Char
foo :: MyType -> MyType
foo (MyInt i) = MyInt (i + 1) -- Or whatever
foo (MyChar c) = case c of {'a' -> MyChar 'A'; k -> MyChar k}
虽然这当然限制了你可以使用的类型。
或者,使用类型类:
class MyClass a where
foo :: a -> a
instance MyClass Int where
foo i = i + 1
instance MyClass Char where
foo c = case c of {'a' -> 'A'; k -> k}
-- N.B. foo :: MyClass a => a -> a
虽然这再一次限制了你可以使用的类型。
答案 1 :(得分:4)
执行此操作的方法是不建议,但是添加Typeable
约束。
foo :: forall a . Typeable a => a -> a
foo x = case eqT :: a :~: Int of -- check if a = Int
Just Refl -> x + 1 -- here we can use x as an Int
Nothing -> x -- here we can not use x as an Int
要实现此功能,您需要一些扩展程序,例如ScopedTypeVariables
和GADTs
。
一般来说,这通常不是一个好主意。在采用这个之前,你应该首先了解你是否真的需要它:Typeable
非常强大,它应该作为最后的手段,当更简单的替代方案是不够的时候。正如AJFarmar所示,自定义类型类可能是您的任务的更好解决方案。
另请注意,如果没有类型类约束,函数foo :: a -> a
,根据其“自由定理”(AKA parametricity属性)只能是标识函数,或者是未定义的(例如无限递归,或者运行时异常)。