완벽을 기하기 위해 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 a
는 String -> [(a, String)]
의 별칭입니다 Read a => Int => ReadS a
를 입력 가지고 readsPrec
기능을 정의합니다. 따라서 우리의 readsPrec
구현은 Int -> String -> [(DB -> (String, String), String)]
유형이어야합니다. 우리는 "선행"인수에 신경 쓰지 않으므로 _
으로 무시합니다. 이 인스턴스에서 단일 결과를 반환하는 데만 신경 쓰므로 [(f, "")]
을 반환합니다.는 해당 key
의 lookup
을 수행하는 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
를 사용해야합니다.
'read :: Read a => String -> a'는 데이터베이스 조회를 수행하는 것이 아니라 문자열 표현에서 특정 유형의 값을 생성하기위한 것입니다. – chepner
유용한 의견을 보내 주셔서 감사합니다. 상사가 저에게 ** read ** 함수를 사용하여 예상 코드 예제를 사용하도록 요청했으며, 해결할 수있는 방법을 찾을 수 없기 때문에 가능한지 확신하고 싶습니다. –
그는'Read' 클래스를 알고 있습니까? 'read' 클래스에 의해 실제로 정의되지 않기 때문에'read' 자체는 오버로드 될 수 없습니다. – chepner