0から5の値を持つリストを表すための型


14

0から5の値を持つリストを表すためのタイプを定義する必要がある練習があります。最初に私はこれを次のように再帰的に解決できると思いました:

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

しかし、これが正しいアプローチだとは思いません。考えの食べ物をください。

回答:


12

私はあなたのためにあなたの演習に答えません-演習のために、自分で答えを理解する方が良いです—しかし、答えに導くべきヒントがここにあります:0から2の要素を持つリストをとして定義することができます

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

ここで、これを5つの要素に拡張する方法について考えます。


10

まあ、再帰的な解決策は確かに通常の、そして実際にはHaskellの素晴らしいものですが、そのとき要素の数を制限するのは少し難しいです。したがって、問題の簡単な解決策として、最初に、bradmから提供された愚かながらも機能する問題を検討してください。

再帰的ソリューションの秘訣は、「カウンター」変数を再帰に渡し、最大許容数に達したときに、より多くの要素のコンスを無効にすることです。これは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

7

完全を期すために、「醜い」代替アプローチを追加しましょう。ただし、これは基本的なものです。

これMaybe aは、値がの形式NothingまたはJust x一部の型であることに注意してくださいx :: a

したがって、上記の値を再解釈することによりMaybe a、リストに0または1つの要素を含めることができる「制限付きリストタイプ」と見なすことができます。

ここで、(a, Maybe a)要素を1つ追加するだけで、リストは1つ((x1, Nothing))または2つ((x1, Just x2))の要素を持つことができる「リストタイプ」になります。

したがって、Maybe (a, Maybe a)は「リストタイプ」であり、リストにはゼロ(Nothing)、1(Just (x1, Nothing))、または2((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)

この回答は、最大長nの多分ベースのリストのタイプファミリーで拡張できます。
左回り、

@leftaroundabout完了。初心者には少々多すぎるかもしれませんが、とにかく追加しました。
カイ

...興味深い型代数で最大3つaのs 。Either () (a, Either () (a, Either () (a, Either () ())))foldr (.) id (replicate 3 $ ([0] ++) . liftA2 (+) [1]) $ [0] == [0,1,2,3]
ネス、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.