2013-01-14 2 views
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]] 

지금 나는이 무한하지 않고 올바른 순서를 것을 알고 있지만 난 그냥 적어도 게시하기 전에 뭔가를 시도하는 것을 보여주고 싶었다. :)

감사합니다.

+10

힌트 : 해당 기능의 유형은 무엇입니까? – Chris

+0

Arrrgghhh! 시도한 것을하지 말아야 할 이유에 대한 많은 유용한 해답이 있지만, 가장 간단하고 명백한 해법을 말하는 사람은 아무도 없습니다. 단지 정수 목록 인 [Int]를 원합니다. – AndrewC

+0

':'는 하스켈의 목록 앞에 뭔가를 넣는 방법입니다. 그래서'1 : [2,3,4]'를하면'[1,2,3,4]'이됩니다. 따라서'func num = num : func (num + 1)'을 정의한 다음'take 100 (func 1)'을 정의 할 수 있습니다. 조심해. 왜냐하면'func'이 정말로 허용 할 것이기 때문에,'take '를 사용하는 것이 좋습니다. 간단히 말해서, 우리는 보통'func 1'을'[1. ..]'로 작성합니다. – AndrewC

답변

2

열쇠는 올바른 유형을 찾는 것입니다.

[1, [2, [3, [4]]]]과 같이하려면 정확히을 수행하십시오. 모든 목록 요소는 동일한 유형이어야하기 때문에 올바르게 작동하지 않습니다.

목록에서 요소를 가져올 때 무엇인가를하기 전에 어떤 유형인지 알 필요가 있습니다. (이것은 유형의 전체 지점 일종의 것입니다. 할 수 있고 할 수 없다). 하스켈의 타입 시스템이 정적이기 때문에 나는이 프로그램이 실행될 때까지 알려진되지 않을 수 있습니다 잡는거야있는 목록 인덱스 때문에

는하지만, 나는 그것이 인리스트의 어떤 요소를 모르고도 입니다 어떤 종류의 알 필요가있다. 그래서 나는 내가 사용하는 색인이 무엇이든 동일한 종류의 것을 얻지 않으면 안된다.

그러나, 그것은 매우 당신이 원하는처럼 뭔가를 할 수있다 : 당신이 익숙하지 않은 경우

type IntegerOrList a = Either Integer [a] 

: 당신이 정수가 될 수도 있고,리스트가 될 수있는 데이터 형식을 원하는 Either 유형의 경우 Either l r 값은 Left x 일부는 x :: l이거나 Right y 일부는 y :: r 일 수 있습니다. 따라서 IntegerOrList a은 값이 정수 또는 무언가 목록 인 형식입니다. 그래서 우리가 그 것들의 목록을 만들 수 있습니다 : 그리스트 안에리스트의 한 단계가 그래서

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

좋아,하지만 우리는 아직리스트 안에리스트 안에리스트를 넣을 수 없습니다 - 다음 유형 [IntegerOrList Bool]의 값은 내부 목록에는 Bool가 포함되어 있으며 목록이 될 수 없습니다. [IntegerOrList (IntegerOrList Bool)] 대신에 목록 내부에 목록을 포함 할 수는 있지만 더 이상 얻을 수는 없습니다. 이 예에서는 정수 또는 목록 인 값을 포함하는 목록을 갖고 있었으며 목록은 정수 또는 목록 인 값을 포함하는 목록이었습니다 ... 그리고 우리가 실제로 원하는 것은 IntegerOrList (IntegerOrList (IntegerOrList ...과 같거나 더 간단합니다. 같은 :

type IntegerOrLists = Either Integer [IntegerOrLists] 

는하지만 그 허용하지 않는다 - 그 가난한 컴파일러 혼란 무한히 많은 종류를 생산하기 때문 유형의 동의어가 순환 할 수 없습니다. 그러나 적절한 데이터 유형 순환 될 수 있습니다

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

의 핵심은 각 항목이를인지한다는 것입니다 :

data IntegerOrLists = I Integer | L [IntegerOrLists] 

지금 당신은 당신의 타입의 정수와 목록을 혼합, 이와 같은 목록을 구축 할 수 있습니다 정수 또는 목록에 I 또는 L 생성자를 사용하여 플래그를 지정해야합니다. 이제 목록의 각 요소는 IntegerOrLists 유형이며 해당 생성자를보고 어떤 요소인지 구분할 수 있습니다. 그래서 형 검사기는 마침내 행복합니다.

+0

정확히 듣고 싶었습니다! 무리 감사! – sheganinans

8

목록의 모든 요소가 동일한 유형이어야하므로 이러한 함수를 작성할 수 없습니다. 만들려는 목록에도 두 요소의 경우 유형 체킹하지 않을 :

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, 두 번째 지능의 목록입니다, 따라서 유형 검사가 실패합니다.

튜플을 사용하여 결과를 표현할 수 있지만 (예 :

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

을 쓸 수 없습니다.

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)]]]] 

이 예제는 단지 이러한 구조는 거의 쓸모가되는

  • 포장 어떤 선물을 사용, 하스켈 이러한 구조를 가질 수

    • 보여줍니다
    (그것으로 무언가를하려고)