检查haskell中的参数类型

时间:2018-04-23 20:26:59

标签: haskell

我有一个函数(a->a),它可以采用不同的类型,但有没有办法确定参数的数据类型是什么? 像

foo :: a -> a
foo a == int =..
foo a == char =..

有没有在haskell做这样的检查?

2 个答案:

答案 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

要实现此功能,您需要一些扩展程序,例如ScopedTypeVariablesGADTs

一般来说,这通常不是一个好主意。在采用这个之前,你应该首先了解你是否真的需要它:Typeable非常强大,它应该作为最后的手段,当更简单的替代方案是不够的时候。正如AJFarmar所示,自定义类型类可能是您的任务的更好解决方案。

另请注意,如果没有类型类约束,函数foo :: a -> a,根据其“自由定理”(AKA parametricity属性)只能是标识函数,或者是未定义的(例如无限递归,或者运行时异常)。