@Andre은 당신의 코드에 대한 최소한의 수정 프로그램을 제공하기 위해 노력. 하스켈에서 오류 처리 작업을 구현하는 관용적 인 방법은 Error
모나드를 사용하는 것입니다. 주된 이유는 combine
을 구현하기 위해 liftM2
라이브러리 함수를 재사용 할 수 있기 때문입니다. throwError
및 return
은 Left
및 Right
으로 바꿀 수 있지만 일반 함수는 코드의 목적을보다 명확하게 설명합니다. combine root left right = liftM2 (Node2 root) left right
: combine = liftM2 . Node2
이상 : combine
이 짧아 질 수 있다는
는
module Err where
import Control.Monad (liftM2)
import Control.Monad.Error (throwError)
data BST2 a = EmptyBST2 | Node2 a (BST2 a) (BST2 a) deriving Show
combine root = liftM2 (Node2 root)
insert2 :: (Ord a) => a -> BST2 a -> Either String (BST2 a)
insert2 elem EmptyBST2 = return $ Node2 elem EmptyBST2 EmptyBST2
insert2 elem (Node2 root left right)
| (elem == root) = throwError "insert2 error: Element already exists."
| (elem < root) = combine root (insert2 elem left) (return right)
| otherwise = combine root (return left) (insert2 elem right)
참고. 가장 잘 이해하는 스타일을 사용하십시오. 오류에 관한 또한
일부 의견은 고정 @Andre :
insert2
는 오류 유형의 다형성이 아니었다 - 항상 실패의 경우에 String
를 반환했습니다. 그래서 대신 형식 선언에 String
을 사용했습니다.
- 목록과 달리 정렬 된 컬렉션에는 형식을 저장할 수 없으며 비교할 수있는 형식 만 트리에 넣을 수 있습니다. 따라서
<
및 ==
이 유형에 대해 구현되어야 함을 나타 내기 위해 트리 값 유형에 Ord a =>
제약 조건을 추가했습니다.
insert2
은 Either
을 반환합니다. Node2 a
이지만 Either String (Node2 a)
이 제공되기 때문에 Left
또는 Right
을 Node2
및 Node2 root (Left foo) right
으로 전달하려고 시도했으나 실패했습니다.
마지막으로, 또 하나의 이유는 throwError
사용하고 return
은 함수가 일반적인 될 것입니다 :
insert2 :: (Ord a, MonadError String m) => a -> BST2 a -> m (BST2 a)
을하고 Either
이외의 MonadError
의 인스턴스를 사용할 수 있지만 {-# LANGUAGE FlexibleContexts #-}
프라그를 추가해야 소스 파일의 맨 위에있는 module
선언 전에.
insert2의 두번째 인수가'String (BST2 a)','BST2 a'만으로 충분할 이유는 없습니다! – adamse
'combine'는 단지'liftM2 '입니다. Node2' – nponeccop