2016-12-19 1 views
1

정적 보셀 (static voxel) 장면을 렌더링하고 하스켈을 배우는 몇 가지 최적화 기법을 테스트하고 있습니다. VoxelId 단순히 Int의 별칭입니다 어디하스켈이 OOP의 클래스 전문화에 해당합니다.

type Voxel = (VoxelId, Position). 

로 정의 복셀 있습니다. 선상의 선형 대수학을 예상하기 때문에, 나는 Position이 3 차원 벡터를 나타 내기를 원했습니다. 라이브러리 (matrix)는 Matrix 데이터 유형 만 구현하지만 Position은 기본 유형이 Matrix이므로 더 많은 계산을 단순화하기 때문에 괜찮습니다.

그러나, Position 3 차원 벡터에 비해 아무것도 할 것이 훨씬 이해가되지 않습니다, 그래서 3 × 1 행렬에 Position을 제한하고 싶습니다, 그래서 함수 서명에 특별히 Position 사용할 때, 나는 ' 3x1 행렬 또는 컴파일 오류가 예상됩니다.

class Matrix 
{ 
    Matrix(int rows, int columns) 
    {} 
} 

class Position : public Matrix 
{ 
    Position() 
    : Matrix (3, 1) 
    {} 
} 

을 내가 다른 곳에가 매트릭스 단 3 × 1 행렬 및 참조를 예상 할 때 Position를 사용

C에서

++ 또는 다른 OO 언어 나는 이런 식으로 뭔가를 할 수 있습니다.

는이 전

matrix :: (rows) -> (columns) -> Matrix 

가 어떻게 Position 모든 작업 Matrix 구현에 대한 재정의하지 않고 하스켈에서이 동작을 복제 할 수있는 생성자 함수를 가지고 사용하고 라이브러리에서 Matrix을 가정 해 봅시다?

+1

하스켈에서 불변이지만 빈 벡터를 구성하는 것은 의미가 없습니다. 당신이 할 수있는 것은 자신 만의 "스마트 생성자"(기본 함수)를 정의하는 것입니다. '(Double, Double, Double)'을 선택하고 행렬을 반환합니다. 좀 더 정적 인 보장을 원할 경우 결과 행렬을 newtype 래퍼에 넣으십시오 (래퍼에 대한 모든 행렬 연산을 정의하거나 매번 언 래핑해야합니다). – chi

+0

Position에 대한 행렬 작업 재정의는 타사 라이브러리 사용의 목적을 무효화하며 최후의 해결책으로 남겨두고있는 것입니다. 더 명확하게하기 위해 원래의 질문을 편집했습니다. –

+0

그런 다음 매번 수동으로 언 랩핑하거나 안전한 강제 변환을 사용해야합니다. 또는 아래와 같이 멍청한 생성자를 사용하십시오. – chi

답변

1

하스켈에는 OOP와 같은 하위 유형이 없습니다.

당신은 당신이 데이터 형식

newtype Position = P { unP :: Matrix ... } 
    deriving (Show) -- , etc. 

그리고 당신이 정말로 내부 표현을 숨기려면, 당신은 자신의 모듈 및 수출 위를 넣을 수 있습니다

position :: Double -> Double -> Double -> Position 
position x1 x2 x3 = 
    Position (newMatrix 1 3 [[x1,x2,x3]]) -- pseudo code 

스마트 생성자를 소유 정의 할 수 있습니다 스마트 생성자 만. 그러나이 작업을 수행하면 필요한 모든 작업을 정의하고이 Position 유형으로 내보낼 것을 요구합니다. 그렇지 않으면 너무 유용하여 유용하지 않습니다.

표현을 숨기지 않는다고 가정하면 PositionMatrix ...은 두 가지 고유 한 유형입니다. 따라서 PositionMatrix에 전달할 수 없습니다. 그래서, 대신

matrixMultiply somePosition someMatrix 

하나

matrixMultiply (unP somePosition) someMatrix 

을하고 Matrix 결과를 얻을 필요가있다. 결과는 대신 Position해야하는 경우, 하나는 수/사용자 정의 곱셈 함수를 정의 할 필요가 :

posMultiply :: Position -> Matrix ... -> Position 
posMultiply m _ | wrongSize m = error "matrix has the wrong size!" 
posMultiply m (Position p) = Position (matrixMultiply m p) 

당신이 원하는 보장 노이즈의 양에 따라이 조금 복잡받을 수 있습니다. 많은 경우에 safe coercions가 통증을 완화시킬 수 있습니다.

더 간단한 대안은 사용자 정의 유형을 사용하지 않는 umber 생성자를 갖는 것일 수 있습니다. 이것은 일반 함수입니다.

position :: Double -> Double -> Double -> Matrix ... 
position x1 x2 x3 = 
    newMatrix 1 3 [[x1,x2,x3]] -- pseudo code 
+0

해답을 가져 주셔서 감사합니다. 저는이 문제를 어떻게 처리 할 수 ​​있을지 생각합니다. 비록 제가 그 솔루션들에 대한 열렬한 팬이 아니라는 것을 인정해야만합니다. (그들은 제가 tho를 생각해내는 것보다 낫습니다.) 사이먼 페이튼 (Simon Peyton)은 하스켈의 유형 시스템 트레이드 오프에 대해 이야기합니다. "하스켈에서는 기존 유형에 새로운 기능을 추가하는 것이 쉽지만 명령형 언어에서는 새로운 기능을 추가하는 것이 쉽습니다. 기존 기능을 입력하지만, 두 경우 모두 inverse가 정말 엉망이됩니다. "그리고 나는 이것이 사실이라고 진술하는 경우라고 생각합니다. –

+0

@ReverentLapwing 네, 그렇습니다. 이를 [ "표현 문제"] (https://en.wikipedia.org/wiki/Expression_problem)라고합니다. – chi