首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell :如何构建异构类型Any

Haskell :如何构建异构类型Any
EN

Stack Overflow用户
提问于 2015-01-10 19:52:51
回答 3查看 110关注 0票数 3

我想要建立一个类型,以匹配任何东西,但从来不使用。

示例:

代码语言:javascript
复制
type Any = forall a. a
f :: (x, Any) -> (Any, y) -> (x,y)
f (x,_) (_,y) = (x,y)

这在{-# LANGUAGE ImpredicativeTypes #-}中编译得很好,但是如果我尝试

代码语言:javascript
复制
f ("hi", 2) (3, (1, 2))

我知道错误:

代码语言:javascript
复制
<interactive>:19:9:
    No instance for (Num a) arising from the literal `2'
    Possible fix:
      add (Num a) to the context of a type expected by the context: a
    In the expression: 2
    In the first argument of `f', namely `("hi", 2)'
    In the expression: f ("hi", 2) (3, (1, 2))

<interactive>:19:13:
    No instance for (Num a) arising from the literal `3'
    Possible fix:
      add (Num a) to the context of a type expected by the context: a
    In the expression: 3
    In the second argument of `f', namely `(3, (1, 2))'
    In the expression: f ("hi", 2) (3, (1, 2))

如果我只想让x和y成为Num的话,那就很好了,但是我计划用它做的事情需要比这更灵活。我知道forall a. a与所有类型都匹配,但只能传递一个永远无法计算和底部的雷击。但是,我不想去调查任何类型的人。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-10 20:20:47

我认为对于Any类型有一个根本的误解。让我通过几个例子来解释一下。

“任何生产者”的功能

代码语言:javascript
复制
f :: ... -> Any

可以用来生成任何类型的值:它返回一个字符串,该字符串同时也是一个整数、一对和大象。具体来说,它返回底部(或者根本不返回,如果您愿意的话)。

“任何消费者”功能

代码语言:javascript
复制
f :: Any -> ...

期望得到任何类型的值:调用者必须同时提供一个字符串,该字符串也是一个整数、一对和大象。具体而言,呼叫者必须通过底部。

您正在尝试传递2,它不是任何类型的--它只属于任何数字类型。因此,类型错误。

如果要编写接受任何内容的函数,则应该编写

代码语言:javascript
复制
type Any = exists a. a  -- INVALID Haskell
f :: Any -> ...

但是,唉,Haskell不允许这种存在主义类型。如果你想要那个类型的话,你必须把它装箱:

代码语言:javascript
复制
data Any = forall a . Any a
f :: Any -> ...

caller = f (Any 'd')

或者,您可以将exists提升到顶层。因为它处于负位置,所以它变成了一个forall

代码语言:javascript
复制
f :: (exists a. a) -> ...
-- becomes
f :: forall a. (a -> ...)
票数 6
EN

Stack Overflow用户

发布于 2015-01-10 20:19:09

从注释中看,真正的问题是:如何键入一个用文字语法["a", False]编写的列表?

答案(幸运的!)就是“你不能”。

您可以创建一个存在类型,并用存在式包装每个元素。如果你想这样做,你可以这样做:

代码语言:javascript
复制
{-# LANGUAGE GADTs #-}
data Box where
    Box :: a -> Box

然后,列表[Box "a", Box False]将在[Box]类型下被很好地键入。但是,如果您愿意对每个元素应用一个函数,那么您最好跳过所有类型的恶作剧,而是这样做:

代码语言:javascript
复制
toss :: a -> ()
toss _ = ()

然后[toss "a", toss False]有非常容易理解的[()]类型。

票数 5
EN

Stack Overflow用户

发布于 2015-01-10 20:21:44

它不能工作,因为您的Any实际上是All。它只能由具有各种类型(类似于undefined)的表达式构造。

您需要使用{-# LANGUAGE ExistentialQuantification #-} to build a realAny``:

代码语言:javascript
复制
data Any = forall a . Any a

这需要数据类型,所以您必须使用Any构造函数来创建值,但是现在您可以这样做:

代码语言:javascript
复制
f :: [(x, Any)] -> [(Any, y)] -> [(x,y)]
f ((x, _) : xs) ((_, y) : ys) = (x,y) : f xs ys
f _ _ = []

> f [("hi", Any 'a'),("you", Any 3)] [(Any "a", 2),(Any Nothing, 4)]
[("hi",2),("you",4)]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27880535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档