2017-03-18 4 views
2

내 haskell 프로그램에서 데이터베이스를 나타내는 목록이 [(key, value)] 형식입니다. 예를 들어 유효한 데이터베이스는 [("key1", "value1"), ("key2", "value2"), ("key3", "value3")]입니다. 데이터는 항상 문자열 유형입니다.하스켈 읽기 함수 오버로드가 두 개 입력

내 질문은 : 그것은 읽기 기능 과부하 및 사용하여 판독 작업를 코딩하는 것이 가능하다는 것을 이런 식으로 : read dbList "key1"? 그렇다면이 문제를 어떻게 해결할 수 있습니까? 출력은 ("not found","value data for key not exists") 또는 ("found", "value1")이어야합니다.

내가 어떻게이 문제를 해결할 수 있는지를 찾았지만 한 가지 입력 매개 변수에 읽기 기능을 사용하는 방법과 특정 유형에 대한 읽기 인스턴스를 생성하는 방법을 알아 냈습니다. 필요합니다. 그러나 두 입력 파라메터로 읽기 기능을 어떻게 든 오버로드 할 수 있는지 궁금합니다.

+0

'read :: Read a => String -> a'는 데이터베이스 조회를 수행하는 것이 아니라 문자열 표현에서 특정 유형의 값을 생성하기위한 것입니다. – chepner

+0

유용한 의견을 보내 주셔서 감사합니다. 상사가 저에게 ** read ** 함수를 사용하여 예상 코드 예제를 사용하도록 요청했으며, 해결할 수있는 방법을 찾을 수 없기 때문에 가능한지 확신하고 싶습니다. –

+0

그는'Read' 클래스를 알고 있습니까? 'read' 클래스에 의해 실제로 정의되지 않기 때문에'read' 자체는 오버로드 될 수 없습니다. – chepner

답변

3

완벽을 기하기 위해 read을 사용하는 방법을 제시합니다. 그러나 이것은 매우 드문 경우이며, 단지 lookup을 사용할 수 있으므로 나쁜 생각이라고 생각합니다.

{-# LANGUAGE FlexibleContexts, FlexibleInstances #-} 

type DB = [(String, String)] 

instance Read (DB -> (String, String)) where 
    readsPrec _ = \key -> let 
    f db = case lookup key db of 
     Just x -> ("found", x) 
     Nothing -> ("not found", "data for " ++ key ++ " does not exist") 
    in [(f, "")] 

는 여기에서 우리는 유형 DB -> (String, String)에 대한 Read의 인스턴스를 정의합니다. read 함수에는 Read a => String -> a 유형이 있으므로이 인스턴스는 read String -> DB -> (String, String)의 오버로드를 제공합니다.

우리의 인스턴스는 ReadS aString -> [(a, String)]의 별칭입니다 Read a => Int => ReadS a를 입력 가지고 readsPrec 기능을 정의합니다. 따라서 우리의 readsPrec 구현은 Int -> String -> [(DB -> (String, String), String)] 유형이어야합니다. 우리는 "선행"인수에 신경 쓰지 않으므로 _으로 무시합니다. 이 인스턴스에서 단일 결과를 반환하는 데만 신경 쓰므로 [(f, "")]을 반환합니다.는 해당 keylookup을 수행하는 DB -> (String, String) 유형의 함수 인 경우 db입니다.

이제 우리가 같이이 인스턴스를 사용할 수 있습니다

> read "foo" [("foo", "bar")] :: (String, String) 
("found","bar") 

> read "baz" [("foo", "bar")] :: (String, String) 
("not found","data for baz does not exist") 

가 다시 나는이 현실에 혼란을 일으킬 수있는 드문 예라고 강조 것이다 코드 그냥 직접 lookup를 사용해야합니다.

4

원하는 기능은 서곡의 일부인 lookup입니다.

> :t lookup 
lookup :: Eq a => a -> [(a, b)] -> Maybe b 
> let dbList = [("key1", "value1")] 
> lookup "key1" dbList 
Just "value1" 
> lookup "key2" dbList 
Nothing 

표시되는 튜플 형식의 출력이 필요한 경우 결과에 패턴 일치시킬 수 있습니다.

case lookup dbList someKey of 
    Just x -> ("found", x) 
    Nothing -> ("not found", "data for " ++ key ++ " does not exist")