4

我不明白为什么我不能构建一个看起来像[1,"1",1.1]haskell 的列表。我不认为是静态类型会妨碍我,因为我认为现在会有一个定义错误的类型,但后来我想到了,运行时head系统没有理由不实例化一个不同的版本headlist 被输入它,因此head [1,"1",1.1]将被输入为List->Int并且head (tail [1,"1",1.1])将被输入为List->String. 既然运行时已经做了很多记账,为什么它不提供各种前奏函数的更高级的多态(或者它是通用的)版本?我在这里想念什么?

4

5 回答 5

16

确实是打字阻止了这种情况。考虑一个列表的定义(注意你的a类型中缺少的类型参数):

data List a = Nil | Cons a (List a)

在中Cons a (List a)您可以看到列表头部的事物类型必须与它后面的元素类型相同。要回答您的问题,您并没有错过很多:正如您所说的运行时可以做到,但在 Haskell 中,您希望在编译时而不是运行时做出这些类型的决定。

如果你想要异构列表,你可以看到 Oleg Kiselyov 在他关于HList(= 异构列表)的工作中的一些魔法。它可能不完全是你想要的,但它的方向大致相同。

于 2011-01-05T07:16:45.653 回答
3

因为在 Haskell 中,所有类型在编译时都是已知的。没有等到运行时才能看到类型是什么。而且因为这足以在动态类型系统中做任何你想做的事情,同时更容易启动。

于 2011-01-05T07:12:33.377 回答
3

正如您所知,实际上有一个用于异构列表的包,使用非平凡的技术,您确实应该确保在深入研究之前充分了解类型系统。由于类型系统,默认情况下您没有这个。Haskell 中的列表不仅仅是一个列表。这是一个 a's 的列表,'a' 是 Int,String,无论你想要什么。但是,一个列表只能包含一种类型的值。

请注意,您可以使用存在量化定义满足某些约束的元素的“异构列表”,但我认为您还没有做到这一点,并且在继续之前应该专注于理解这里的其他答案。

于 2011-01-05T11:17:56.753 回答
3

有一种称为 HList 的异构列表类型(可在 Hackage 上获得),但请注意,您的列表内容可能有一个类型。考虑这样的事情:

history = [-12, "STATEMENT END", (-244, time January 4 2010), ...]

您的数据有一种难以出现的类型,例如:

data HistoryEntry = Withdrawal Int | StatementClosing | ScheduledPayment Int CalendarTime

history = [Withdrawal 12, StatementClosing, ScheduledPayment 244 (time January 4 2010)]

在许多情况下,您的数据具有您只需要寻找的类型。

于 2011-01-05T17:32:48.917 回答
3

查看异构集合

{-# OPTIONS -fglasgow-exts #-}
--
-- An existential type encapsulating types that can be Shown
-- The interface to the type is held in the show method dictionary
--
-- Create your own typeclass for packing up other interfaces
--
data Showable = forall a . Show a => MkShowable a

--
-- And a nice existential builder
--
pack :: Show a => a -> Showable
pack = MkShowable

--
-- A heteoregenous list of Showable values
--
hlist :: [Showable]
hlist = [ pack 3
        , pack 'x'
        , pack pi
        , pack "string"
        , pack (Just ()) ]

--
-- The only thing we can do to Showable values is show them
--
main :: IO ()
main = print $ map f hlist
    where
        f (MkShowable a) = show a

{-

*Main> main
["3","'x'","3.141592653589793","\"string\"","Just ()"]

-}
于 2011-01-05T22:20:42.943 回答