2014-10-11 1 views
2

저는 C# 배경에서 시작하여 F #을 배우기 시작했습니다. 나는 매우 단순한 과제에 붙어있는 것처럼 보입니다.F #의 파일 시스템 구현

GIVEN (옵션 변경이 아님) 유형의 파일 시스템을 구현해야합니다. 여기서 'a는 이름을 의미하고'b는 데이터를 의미합니다.

type Tree<'a,'b> = Node of list<'a * Tree<'a,'b>> 
       | Leaf of 'b 

파일 시스템은 다음 파일/디렉토리 이름이 문자열에 의해 주어진이 유형의 인스턴스가 될 것이다 '는 문자열로 파일 내용'나. 디렉토리는 노드와 파일이어야합니다. 컴파일러는 나무가 아닌 목록을 기대로

type FileSystem = Tree<string,string> 

///(directory) 
// /home (directory) 
// /home/.emacs (file) 
// /home/.ssh (directory) 
// /home/.ssh/id_rsa (file) 
// /usr (directory) 
// /usr/bin (directory) 
// /usr/bin/bash (file) 
// /usr/bin/emacs (file) 

내가에 붙어 ...

let fs = Node["/", 
      Node["home", 
       Node[".ssh", 
        Node["id_rsa", Leaf("id_rsa_DATA")] 
        ] 
       ] 
       ] 

노드의 더 많은 노드 나 잎을 추가하려는 시도가 실패? 이와 같은 트리를 구축하는 올바른 구문은 무엇입니까? 내가 구현해야하는이 나무와

:

ls : FileSystem -> list<string> // list root directory 
subfs : FileSystem -> list<string> -> FileSystem // return the filesystem you find at that path 
ls' : FileSystem -> list<string> -> list<string> // list data of directory files at given path (fail if its just a file) 

편집 :

그래서 그것입니다 :

let fs = Node["/", 
       Node["home/", 
        Node[".ssh/", 
         Node["id_rsa", Leaf("id_rsa_DATA") 
          ]; 
        ".emacs", Leaf(".emacs_DATA") 
        ]; 
        "usr/", 
        Node["bin/", 
          Node["bash", Leaf("bash_DATA"); 
           "emacs", Leaf("emacs_DATA") 
           ]; 
        ".emacs", Leaf(".emacs_DATA")]; 
        ] 
      ] 

지금은 나열 할 수 있습니다 방법 디렉토리와 subfilesystem (LS, subfs, ls ')?

답변

1

디렉토리 (또는 하위 디렉토리)의 경우 string * Node이고 파일의 경우 string * Leaf이되어야합니다 ('a * Tree<'a,'b>).이 같은 끝낼 것

그 방법 :

+0

으로 정확히 정의해야하지만 전체 노드가 목록이어야합니다. 프로젝트 요구 사항이며 변경할 수 없습니다. – mpkfa

+0

유형을 잘못 읽었습니다. 고독한 튜플 대신 목록 용으로 업데이트했습니다. –

+0

좋아요, F # Interactive를 사용한 후에 마침내 맞았습니다. :) –

1

이것이 원하는 것에 더 가깝습니까?

즉, 각 노드는 값 'a의 튜플이고 유형이 < 인 자식 목록이', 'b>입니까?

type Tree<'a,'b> = 
    | Node of 'a * Tree<'a,'b> list 
    | Leaf of 'b 

let fs = Node("/", 
       [Node("home", 
         [Node(".ssh", 
           [Node("id_rsa", 
            [Leaf("id_rsa_DATA")] 
           )] 
         )] 
       )] 
      ) 

let rec f n = 
    match n with 
    | Node(".ssh",nodeList)::tail -> 
     printfn "found .ssh" 
     f tail 
     f nodeList 
    | Leaf(leafStr)::tail -> 
     printfn "found leaf %s" leafStr 
     f tail 

f [fs] 

이 구조체의 재귀의 경우는 필요 이상으로 일을 조금 더 복잡하다, 그래서 ... 당신은이 정의를 더 좋아 수 있습니다

type Tree<'a,'b> = 
    | Node of 'a * Tree<'a,'b> list 
    // omit the leaf and define it as a node with an empty list of children 

물론 않는 한 당신 당신이 작업에 대한 자세한 명시하고 싶습니다 :

type FileSys<'a,'b> = 
    | Folder of 'a * FileSys<'a,'b> list 
    | File of 'b 

우리가 파일 및 폴더 라벨의 시스템에 대해 이야기하는 경우, 그것은 일반해야합니까?

type FileSys = 
    | Folder of string * FileSys list 
    | File of string 

제네릭 형식보다 차별화 된 공용 구조체를 사용하는 솔루션으로가는 것이 더 간단합니다. 그렇게한다면 FSHARP의 풍부한 구조 집합과 패턴 매칭에 대해 더 많은 신뢰를 쌓을 수 있습니다. F # 추론을 통해 문제 공간을 도구로 만드는 것은 동시에 탐색 적 방식으로 발생할 수 있습니다.

+0

가 실제로 트리 노드가리스트 < 'A * 트리 <'a,'b>> – mpkfa