Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
定义签名中可能包含的haskell函数_Haskell - Fatal编程技术网

定义签名中可能包含的haskell函数

定义签名中可能包含的haskell函数,haskell,Haskell,我不清楚如何在haskell中编写函数签名,尤其是使用Maybe。考虑: f :: Maybe a -> Maybe a f = \a -> a main = print (f (Just 5)) 这是可行的,但为什么函数签名不能是这样呢 f :: Maybe -> Maybe 因为f只接受Maybe类型并返回Maybe类型 相关:如果我想让Maybe类型更具体,成为Maybe Int,为什么这不起作用 f :: Maybe Int a -> Maybe Int

我不清楚如何在haskell中编写函数签名,尤其是使用
Maybe
。考虑:

f :: Maybe a -> Maybe a
f = \a -> a

main = print (f (Just 5))
这是可行的,但为什么函数签名不能是这样呢

f :: Maybe -> Maybe 
因为
f
只接受
Maybe
类型并返回
Maybe
类型

相关:如果我想让Maybe类型更具体,成为
Maybe Int
,为什么这不起作用

f :: Maybe Int a -> Maybe Int a
f = \a -> a

main = print (f (Just (Int 5)))

(我正在使用
runhaskell test.hs运行所有代码)

似乎您对类型变量感到困惑。首先,在

f :: Maybe a -> Maybe a
f = \a -> a
第一行的
a
与第二行的
a
无关,我们可以写:

f :: Maybe a -> Maybe a
f = \x -> x
甚至

f :: Maybe foo -> Maybe foo
f = \bar -> bar
a
是代表类型的变量。因此,
f
这里声明,
f
同时有一大堆类型:

f :: Maybe Int -> Maybe Int
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe (Maybe Bool)
...
等等。这并不是像我怀疑你们所想的那个样对论点进行“标记”。两个
a
是相同的,这意味着参数类型必须是相同的结果类型。如果我们说
f::maybeaa->maybeab
我们会得到这个家庭:

f :: Maybe Int -> Maybe Bool
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe Int
...
也就是说,
a
b
现在可以代表不同的类型,但是参数和结果仍然必须是
可能是

你不能说的原因

f :: Maybe -> Maybe
是因为
可能
不是一个类型——它是一个类型构造函数。如果你给它一个类型,它会给你一个类型。因此,
Maybe Int
Maybe String
都是类型,一般来说,
Maybe a
是类型,只要
a
是类型

Maybe Int a
(解析为
(Maybe Int)a
)没有意义,因为
Maybe Int
不是类型构造函数——它不接受任何其他参数


建议阅读:来自LYAH。

似乎您对类型变量感到困惑。首先,在

f :: Maybe a -> Maybe a
f = \a -> a
第一行的
a
与第二行的
a
无关,我们可以写:

f :: Maybe a -> Maybe a
f = \x -> x
甚至

f :: Maybe foo -> Maybe foo
f = \bar -> bar
a
是代表类型的变量。因此,
f
这里声明,
f
同时有一大堆类型:

f :: Maybe Int -> Maybe Int
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe (Maybe Bool)
...
等等。这并不是像我怀疑你们所想的那个样对论点进行“标记”。两个
a
是相同的,这意味着参数类型必须是相同的结果类型。如果我们说
f::maybeaa->maybeab
我们会得到这个家庭:

f :: Maybe Int -> Maybe Bool
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe Int
...
也就是说,
a
b
现在可以代表不同的类型,但是参数和结果仍然必须是
可能是

你不能说的原因

f :: Maybe -> Maybe
是因为
可能
不是一个类型——它是一个类型构造函数。如果你给它一个类型,它会给你一个类型。因此,
Maybe Int
Maybe String
都是类型,一般来说,
Maybe a
是类型,只要
a
是类型

Maybe Int a
(解析为
(Maybe Int)a
)没有意义,因为
Maybe Int
不是类型构造函数——它不接受任何其他参数


建议阅读:来自LYAH。

可能是一个类型构造函数,本质上是一个类型级函数。它接受一个类型(例如
Int
)并返回一个类型(例如
可能是Int
)。类型的“类型”称为种类:具有值的类型,如
Int
,称为
*
。接受一个参数的类型构造函数的类型是
*->*
。您可以使用
:kind
/
:k
命令在GHCi中看到这一点:

> :k Int
Int :: *

> :k Maybe
Maybe :: * -> *

> :k Either
Either :: * -> * -> *
在像
maybea a->maybea a
这样的签名中,
a
是一个类型变量,当您调用函数时,它会被替换为特定类型。(隐式地说,这意味着
对于所有a.maybea->maybea
,如果启用扩展,例如
ExplicitForall
ScopedTypeVariables
,您可以自己编写)

因此,如果您在
Maybe Int
上调用
f::Maybe a->Maybe a
,那么
f
在该调用站点具有类型
Maybe Int->Maybe Int
,因为
a
已被实例化为
Int

编译器拒绝
Maybe Int a
,因为您向
Maybe
提供了两个参数,而它只接受一个参数。(
a
不是参数的名称,而是类型的参数。)同样,它拒绝
Maybe->Maybe
,因为您没有给
Maybe
任何参数,所以您试图将两种类型的
*->*
传递给函数arrow构造函数
(>)
,它接受类型为
*
的参数:

> :k (->)
(->) :: * -> * -> *
另一方面,可以编写类似于
Maybe->Maybe
的内容,并将其扩展为
maybea->maybea
,这有时可能很有用,但几乎可以肯定这不是您现在想要做的

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}

type (~>) f g = forall a. f a -> g a

f :: Maybe ~> Maybe
f x = x

这里,类型同义词
Maybe~>Maybe
扩展为
forall a。可能是一个->可能是一个
,可以缩写为
可能是一个->可能是一个
,您以前编写的签名。

可能是一个类型构造函数,本质上是一个类型级函数。它接受一个类型(例如
Int
)并返回一个类型(例如
可能是Int
)。类型的“类型”称为种类:具有值的类型,如
Int
,称为
*
。接受一个参数的类型构造函数的类型是
*->*
。您可以使用
:kind
/
:k
命令在GHCi中看到这一点:

> :k Int
Int :: *

> :k Maybe
Maybe :: * -> *

> :k Either
Either :: * -> * -> *
在像
maybea a->maybea a
这样的签名中,
a
是一个类型变量,当您调用函数时,它会被替换为特定类型。(隐式地说,这意味着
对于所有a.maybea a->maybea a
,如果启用ex,您可以自己编写