我有一个自定义数据类型如下:
data MyType a = Nothing
| One a
我们的想法是拥有一个返回数据类型的函数。例如,
func (One Char)
应该返回Char
- 返回数据类型
我尝试按照以下方式实施func
:
func :: MyType a -> a
func (One a) = a
-- don't worry about Nothing for now
编译的代码但是当我尝试运行func (One Char)
时,它给出了一个错误:Not in scope: data constructor ‘Char’
发生了什么事?
答案 0 :(得分:2)
尝试func (One "Hello")
它会起作用。
原因是Haskell认为你试图给它一个数据构造函数因为你写了一个大写的Char
所以只是给它一些真正的价值;)
BTW:如果你真的想要提供类型 Char
:在Haskell中通常不可能,因为你需要一个依赖类型的上限(参见{{ 3}}例如)。
答案 1 :(得分:1)
这并不是真的如何运作。 Char
是一种类型,因此我们可以编写
func :: MyType Char -> Char
意思是我们期待"某事" MyType
成为Char。
检查参数的类型可能在Java等方面有效,但不是函数式编程的工作方式。
答案 2 :(得分:0)
我不认为你真的希望通过你目前对Haskell的理解(这对我来说很棒,而且我&#39)很有可能。已经有一段时间了,但如果你真的这么做,你实际上可以得到一些非常接近的东西。
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-} --might as well
-- I renamed Nothing to None to avoid conflicting with Maybe.
-- Since we're using DataKinds, this creates not only a type
-- constructor MyType and data constructors None and One,
-- but also a *kind* MyType and *type* constructors None and
-- One.
data MyType a = None | One a
-- We can't make a *function*, func, to take One Char and
-- produce Char, but we can make a *type function* (called
-- a type family) to do that (although I don't really know
-- why you'd want this particular one.
type family Func (a :: MyType k) :: k
type instance Func (One a) = a
现在,如果我们写
Prelude> '3' :: Func (One Char)
GHCi非常满意。事实上,我们可以使这种类型的功能更加通用:
type family Func2 (a :: g) :: k where
Func2 (f a) = a
现在我们可以写
'c' :: Func2 (One Char)
但我们也可以写
'c' :: Func2 (Maybe Char)
甚至
'c' :: Func2 (Either Char)
'c' :: Func2 ((Either Int) Char)
但如果您认为有什么事情发生,
'c' :: Func2 (Maybe Int)
或
'c' :: Func2 Char
会出错。