用于表示具有0到5个值的列表的类型


13

我有一个练习,我必须定义一个类型来表示具有0到5个值的列表。首先,我认为我可以像这样递归解决此问题:

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

但是我认为这不是正确的方法。你能给我个思路吗?

Answers:


11

我不会为您回答您的练习-对于练习,最好自己弄清楚答案-但这是一个提示,可以引导您找到答案:您可以定义一个包含0到2个元素的列表

data List a = None | One a | Two a a

现在,考虑如何将其扩展到五个元素。


9

好吧,递归解决方案在Haskell中当然是正常的,实际上是一件好事,但是限制元素的数量却有些棘手。因此,对于该问题的简单解决方案,首先考虑bradm给出的愚蠢但可行的解决方案。

使用递归解决方案时,诀窍是在递归下传递一个“ counter”变量,然后在达到允许的最大值时禁用更多的元素。使用GADT可以很好地做到这一点:

{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeInType, StandaloneDeriving #-}

import Data.Kind
import GHC.TypeLits

infixr 5 :#
data ListMax :: Nat -> Type -> Type where
  Nil :: ListMax n a
  (:#) :: a -> ListMax n a -> ListMax (n+1) a

deriving instance (Show a) => Show (ListMax n a)

然后

*Main> 0:#1:#2:#Nil :: ListMax 5 Int
0 :# (1 :# (2 :# Nil))

*Main> 0:#1:#2:#3:#4:#5:#6:#Nil :: ListMax 5 Int

<interactive>:13:16: error:
     Couldn't match type 1 with 0
      Expected type: ListMax 0 Int
        Actual type: ListMax (0 + 1) Int
     In the second argument of ‘(:#)’, namely 5 :# 6 :# Nil
      In the second argument of ‘(:#)’, namely 4 :# 5 :# 6 :# Nil
      In the second argument of ‘(:#)’, namely 3 :# 4 :# 5 :# 6 :# Nil

非常感谢。因为这是初学者练习,所以我认为这是更简单的方法。但是我也会考虑您的方法。
mayerph

6

为了完整起见,让我添加一个“丑陋”的替代方法,但这是非常基本的。

回想一下,Maybe a是一种类型,其值是形式的NothingJust x为一些x :: a

因此,通过重新解释上述值,我们可以将其Maybe a视为“受限列表类型”,其中列表可以具有零个或一个元素。

现在,(a, Maybe a)只需添加一个元素即可,因此它是“列表类型”,其中列表可以具有一个((x1, Nothing))或两个((x1, Just x2))元素。

因此,Maybe (a, Maybe a)是“列表类型”,其中列表可以具有零(Nothing),一个(Just (x1, Nothing))或两个((Just (x1, Just x2))元素。

您现在应该能够理解如何继续。让我再次强调,这不是使用方便的解决方案,但无论如何,这是(IMO)很好的练习。


使用Haskell的一些高级功能,我们可以使用类型族来概括以上内容:

type family List (n :: Nat) (a :: Type) :: Type where
    List 0 a = ()
    List n a = Maybe (a, List (n-1) a)

可以使用基于Maybe的max-length n列表类型类型来扩展此答案。
leftaroundabout

@leftaroundabout完成。对于初学者来说可能有点太多,但无论如何我还是添加了它。

...有趣的类型代数中最多3 as 。Either () (a, Either () (a, Either () (a, Either () ())))foldr (.) id (replicate 3 $ ([0] ++) . liftA2 (+) [1]) $ [0] == [0,1,2,3]
威尔·内斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.