2017-05-10 6 views
0

ネストされたタプルを返すことになっている関数に苦労しています。具体的には、関数の型付けによって多くの問題が生じています。簡略化バージョンは、以下である:タプル型の再利用

tupfnc :: ????? 
tupfnc [a] = (a,()) 
tupfnc (a:as) = (a,tupfnc as) 

考え項目のリスト([0,1,5,3]と言う)と、このようなタプルに入れ子にそれらを取り込むことである:(0、(1、 (5、(3、()))))。

私のinital考えはそうのような宣言で行くことにした。

tupfnc :: [a] -> (a,b) 

は、しかし、(この例の)3行目は、エラー

Solver.hs:56:17: error: 
    • Couldn't match expected type ‘(a, b)’ 
        with actual type ‘[(a, (a, b0))]’ 
    • In the expression: [(a, tupfnc as)] 
     In an equation for ‘tupfnc’: tupfnc (a : as) = [(a, tupfnc as)] 
    • Relevant bindings include 
     as :: [a] 
     a :: a 
     tupfnc :: [a] -> (a, b) 

任意の提案スロー?

+3

がここにいくつかオフがあります。まず、あなたの "配列"(リスト)は常に_same_タイプを含みます。 '' a''は '' Int''ではないので、 '[0,1、 'a'、3]'は使えません。次に、リストやタプルを返しますが、その型は異なりますので、どちらもできません。そして最後に、 '(a、b)'と '(a、(a、b)) 'という型は' b〜(a、b) 'を除いて異なります。 'InPair a = Stop | 'を使う必要があります。 InPair a(InPair a) 'を作成すると、リストに戻ります。タイプレベルの不均一リストを探していますか? – Zeta

+0

私の悪い、私の頭は質問を書くときに真っ直ぐではなかった。私はそれをより正確に編集しました。リストのアイテムはすべて同じタイプであるとみなされます。 b〜(a、b)についてのあなたのコメントは、私が探していた場所のほうが多かったです。私は、無限型を返す関数を定義する方法を知らない(それらは何と呼ばれているのだろうか?)。また、タイプレベルの不均一リストも見ていきます。 –

+1

編集しても '(a、())'と '[(a、...)]を返します。あなたはリストやタプルを返しますが、それらは異なるタイプです。これはXY問題のようです。あなたは実際に何をしたいですか? – Zeta

答えて

1

リストの長さに関するタイプレベルの情報がない限り、これはできません。場合は、次の操作を行うことができるとしたVectorと呼ばれるリストの変種想像:

{-# LANGUAGE GADTs, PolyKinds, DataKinds, TypeFamilies, TypeOperators #-} 

-- | Peano natural numbers 
data Nat = Z | S Nat 

-- Just for convenience... 
type N0 = Z 
type N1 = S N0 
type N2 = S N1 
type N3 = S N2 
type N4 = S N3 
type N5 = S N4 
type N6 = S N5 
type N7 = S N6 
type N8 = S N7 
type N9 = S N8 

-- | Equivalent to a list, but carries information about its length with it 
data Vector (n :: Nat) a where 
    Nil :: Vector Z a 
    (:-) :: a -> Vector n a -> Vector (S n) a 

infixr 5 :- 

は今、私たちは、その適切なネストされたタプルに番号を変換タイプファミリーを定義することができます。

type family NestedTuple (n :: Nat) (a :: *) where 
    NestedTuple Z  a =() 
    NestedTuple (S n) a = (a, NestedTuple n a) 

最後に、Vector n aをネストされたタプル形式に変換する関数を定義できます。

toList :: Vector n a -> NestedTuple n a 
toList Nil =() 
toList (x :- xs) = (x, toList xs) 

あなたはGHCiのでこれを試すことができます。

ghci> :set -XFlexibleContexts 
ghci> toList ("foo" :- "bar" :- "baz" :- Nil) 
("foo",("bar",("baz",())))