여기에서 설명한 것은 본질적으로 동형을 기준으로 클래스 인스턴스를 정의하는 것입니다. 이것은 get
및 set
함수를 정의하여 분명히 달성 할 수 있지만 좀 더 명확하게하기 위해 to
및 fro
이라고 부르기로합니다.
toSI :: String -> Integer
fromSI :: Integer -> String
instance Num String where
a + b = fromSI $ (toSI a) + (toSI b)
abs = fromSI . abs . toSI
...
이
실제로 쓸 수있는 아주 쉽게 정의하고주의 깊게 글로벌 typeclass을 오염시키지하기 위해 많은 규칙을 따라야합니다, 자동으로
(to, fro)
이상
하지만이 시스템을 클래스의 인스턴스를 올려 상용구를 줄이기위한 몇 가지 값이있을 수 있습니다 정크가있는 인스턴스 공간.
특히, 우리는 동형을 형성하도록 (to, fro)
을 요청할 수 있습니다. 즉, 왕복 왕복 은 두 방향 모두입니다. 다른 말로 표현하자면 어떤 정수라도 주어진 n
이라는 것을 의미한다면 어떤 수단으로도 을 n
과 구별 할 수 없어야합니다. (물론 계산 속도 같은 것은 무시됩니다). 또한 에 대한 동일한 속성이 있어야합니다. 문자열 s
: toSI (froSI s)
은 과 구별 할 수 있어야합니다.
두 번째 질문은 분명히 실패합니다. "I am not a number!"
은 왕복 여행에서 오류를 발생시킵니다. 순수한 코드에서 오류를 던지는 것이 위험하고, 코드가 가져 오는 사람의 코드를 위험에 빠뜨리고 오염시키는 typeclasses를 가진 많은 이유가 있습니다.
모든 문자열이 유효한 숫자가 아니기 때문에 이것이 유일한 원인이라고 지적 할 수 있습니다. fromSI . toSI
은 항상 문제가있는 것 같지만 toSI . fromSI
해야합니다. 예를 들어 instance Num String
을 인스턴스화하는 것과 같은 작업에만 영향을 미치고 대신 (toSI, froSI)
쌍을 사용하여 Integer
에 대해 instance
을 얻는다면 String
은 좋은 위치에있을 것입니다. 아마도.
사용해보기. String
는 우리가 우리가
(1 <> 2) <> 3 == 123
1 <> (2 <> 3) == 123
(0 <> 1) <> 1 == 11
0 <> (1 <> 1) == 11
처럼 "정수을 연결"우리가주의 인 경우 "" -> 0
를 정의하는 대신 만들어주는 mappend = toSI . mappend . fromSI
통해 mappend
을 구현하는 경우이
instance Monoid [a] where -- if a ~ Char then this is String
mempty = []
mappend as bs = as ++ bs
처럼 보이는 Monoid
의 인스턴스 그러면 우리는 유용한 mempty
을 얻을 수 있습니다.
mempty = toSI mempty
잘 작동해야하는 것처럼 보입니다. 실제로 Monoid
의 Integer
은 String
(이유는 내가 이 아니라 Int
이 아닌 이유를 생각해보십시오.)와 함께 "단방향 동형 이성"으로부터 계승되었습니다. 더 구체적으로는 Monoid
typeclass에있는 함수를 사용하여 작성한 테스트를 통해 에서 toSI (fromSI n)
을 구별 할 수 없으므로이 매핑을 수행하는 데 "충분 함"입니다.
하지만 다른 문제가 발생합니다. Integer
에는 이미 Monoid
인스턴스가 있습니다. 이미 약 10 그들, 그래서 우리는 정식 모노 이드에 대한 예를 typeclass로 이러한 경우 중 하나를 선택하여 정보를 많이 잃고있어 가장 인기있는 존재의 곱셈과 또한
instance Monoid Integer instance Monoid Integer
mempty = 0 mempty = 1
mappend = (+) mappend = (*)
있습니다. Integer
은 String
과 함께 "일방적 인 동형 이성"(a.k.a. "retract")을 통해 Monoid
이되지만 덧셈을 통해 스트립 핑을 통해 또한 곱하기가있는 스트립 핑을 통해 더 정확하게 표현됩니다.
정말 우리는 Monoid
패키지이 Integer
단지의 Addition
속성을 사용하는 전문되었음을 나타냅니다 Sum
및 Product
같은 것들을 정의하는 이유 주위에 그 정보를 유지하려는.
그리고 그 날이 끝날 무렵에는 동형 이상의 인스턴스에 대해 타입 클래스 인스턴스를 들어 올리는 것과 정확히 같은 문제가 있습니다. 일반적으로 유형에는 동형과 수축이 많이 포함되어있어 이러한 방식으로 학대를받을 수 있으며 실제로 표준적이고 법을 준수하는 인스턴스를 갖는 것은 어렵습니다. 당신이 그것을 발견 할 때, 동형 화를 사용하여 결국 그렇게하더라도, 명시 적으로 코드 세금을 쓸 가치가 있습니다.
당신이 newtype
같은 악기를 가지고 표준 선택과 신속 Control.Newtype
package 밖으로 일반적인 GeneralizedNewtypeDeriving
확장에서 그냥 "아래의"newtype
계층의 모든 방법 또는 직접 Iso
, au
and auf
영감을 무엇에 액세스하기위한 라이브러리의 회전이없는 및 전체 Wrapped
, ala
, alaf
lens
의 메커니즘.
기본적으로이 기계는 다양한 동형 이형성, 특히 newtype
에 의해 유도 된 인스턴스에 대해 풍부한 이야기를하기에 적합합니다.
'get'? '설정'? 나는 당신이 하스켈이 주장하는 것과는 아주 무관 한 것을 요구하고 있다고 생각한다. 자동 형 변환을하는 거지? 그건 좋은 생각이 아니다; 그것은 양방향 유형 공제의 이점으로부터 당신을 박탈합니다.이 공제는 몇 가지 명백한 변환 기능이 합리적으로 도입 할 수있는 것보다 훨씬 더 많은 상용구를 피합니다. - 또한 유형은 대략 동형이 아니기 때문에 특히 나쁜 예입니다. ''int ','set (-1) :: Bool' 또는''Set [1,2,3] :: Maybe Int'와 같은 문제로 무엇을 할 것입니까? – leftaroundabout
컴파일 타임에 선언을 간단한 인스턴스 선언으로 대체 할 수 있어야한다고 생각합니다. 따라서이 제안은 하스켈의 파생 메커니즘과 상당히 관련이 없지만 형식 시스템은 변경되지 않아야합니다. 아마도 이름 변경이 순서에 있습니다. – user1502040
대체 할 선언은 무엇입니까? 어떻게 사용하고 싶은지를 보여 줄 수 있습니까? – leftaroundabout