3

これに似た(できれば無限の)数値のリストを返す関数を作成する可能性があるかどうか疑問に思っていました. [1、[2、[3、[4]]]]。

私が得た最も近いものはこれでした。

func list 0 = list
func list num = func newList (num-1) 
                where newList = list ++ [[num]]

こんな感じで使われています。

func [] 3

これを返します。

[[3],[2],[1]]

これが無限ではなく、正しい順序ではないことはわかっていますが、投稿する前に少なくとも何かを試みていたことを示したかっただけです。:)

本当にありがとう!

4

3 に答える 3

8

リストのすべての要素は同じ型でなければならないため、このような関数を作成することはできません。作成するリストは、要素が 2 つだけの場合でも型チェックされません。

Prelude> :t [1::Int,[2::Int]]

<interactive>:1:9:
    Couldn't match expected type `Int' with actual type `[Int]'
    In the expression: [2 :: Int]
    In the expression: [1 :: Int, [2 :: Int]]

最初の要素は Int で、2 番目の要素は Int のリストであるため、型チェックは失敗します。

結果をタプルで表現できますが、たとえば

Prelude> :t (1::Int,(2::Int,(3::Int,4::Int)))
(1::Int,(2::Int,(3::Int,4::Int))) :: (Int, (Int, (Int, Int)))

必要な要素の数によって結果の型が変わるため、まだ関数を書くことはできません。f仮想関数を呼び出しましょう:

f 1 :: (Int)
f 2 :: (Int,(Int))
f 3 :: (Int,(Int,(Int)))
...

f引数で型が変わるのでf書き込めません。

于 2013-01-14T10:19:30.853 に答える
2

重要なのは、正しいタイプを考え出すことです。

のようなものが必要な場合は、すべてのリスト要素が同じ型でなければならないため[1, [2, [3, [4]]]]、それを正確に行うことはできません。

これは理にかなっています。なぜなら、リストから要素を取得するとき、それを使って何かを行う前に、それがどのような型であるかを知る必要があるからです (これが型の要点のようなもので、何ができるか、何ができるかを教えてくれます。)物とは関係ありません)。

しかし、Haskell の型システムは静的であるため、リストのどの要素であるかを知らなくても、どの型であるかを知る必要があります。取得しているリスト インデックスは、プログラムが実行されるまでわからない可能性があるからです。したがって、使用するインデックスが何であれ、同じタイプのものを取得する必要があります。

ただし、あなたが望むものと非常によく似た何かをすることは可能です: 整数であるかもしれないデータ型、またはリストであるかもしれないデータ型が欲しいです:

type IntegerOrList a = Either Integer [a]

タイプに慣れていない場合Either、値はsomeまたはsomeのEither l rいずれかになります。値が整数または何かのリストのいずれかである型も同様です。したがって、それらのリストを作成できます: 以下は type の値です:Left xx :: lRight yy :: rIntegerOrList a[IntegerOrList Bool]

[Left 7, Left 4, Right [True, False], Left 8, Right [], Right [False]]

オーケー、それでリスト内のリストの 1 つのレベルですが、まだリスト内のリスト内にリストを入れることはできません。内部のリストにはBools が含まれており、リストにすることはできません。代わりに があれば[IntegerOrList (IntegerOrList Bool)]、リスト内のリスト内にリストを含めることができますが、それでもそれ以上のことはできません。この例では、整数またはリストのいずれかである値を含むリストがあり、リストは整数またはリストである値を含むリストであり、... 本当に必要なのは のようなものIntegerOrList (IntegerOrList (IntegerOrList ...、またはもっと単純に何かお気に入り:

type IntegerOrLists = Either Integer [IntegerOrLists]

しかし、それは許可されていません。型シノニムを再帰的にすることはできません。これは、貧弱なコンパイラを混乱させる無限に大きな型を生成するためです。ただし、適切なデータ型再帰的である可能性があります。

data IntegerOrLists = I Integer | L [IntegerOrLists]

これで、整数とタイプのリストを組み合わせて、次のようなリストを作成できます。

L [I 1, L [I 2, L [I 3, L [I 4]]]]

重要なのは、各項目が整数であるかリストであるかは、IまたはLコンストラクターを使用してフラグを立てる必要があるということです。これで、リストの各要素は typeIntegerOrListsになり、そのコンストラクターを見ることでそれがどれであるかを区別できます。したがって、タイプチェッカーはついに満足しています。

于 2013-01-14T15:40:14.477 に答える
1
{-# LANGUAGE ExistentialQuantification #-}

class Foo a

instance Foo Int
instance Foo [a]

data F = forall a. Foo a => F a

test = F [F (1 :: Int), F [F (2 :: Int), F [F (3 :: Int), F [F (4 :: Int)]]]]

この例は、

  • Haskellでそのような構造を持つことができるようにするには、ギフトラッピングを使用してください
  • これらの構造が実質的に役に立たないこと (それを使って何かをしようとする)
于 2013-01-14T14:57:22.670 に答える