User Tools

Site Tools


study:haskell:ch6

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
study:haskell:ch6 [2014/01/13 14:12]
jdj [When do overlapping instances cause problems?]
study:haskell:ch6 [2019/02/04 14:26] (current)
Line 1023: Line 1023:
 ------------------------------------------------- -------------------------------------------------
  
-instance 구현 오버랩핑은 ​제 사용할??+instance 구현 오버랩핑은 ​제 문제를 발생시킬까?
  
-위 정의들을 ​소스파일에 작성하고 ghci 로 읽어드릴때,​+<​code>​ 
 +-- file: ch06/​Overlap.hs 
 +class Borked a where 
 +    bork :: a -> String 
 + 
 +instance Borked Int where 
 +    bork = show 
 + 
 +instance Borked (Int, Int) where 
 +    bork (a, b) = bork a ++ ", " ++ bork b 
 + 
 +instance (Borked a, Borked b) => Borked (a, b) where 
 +    bork (a, b) = ">>"​ ++ bork a ++ " " ++ bork b ++ "<<"​ 
 +</​code>​ 
 + 
 +위 코드는 ​소스파일에 작성하고 ghci 로 읽어드릴때,​
 처음에는 문제가 없어보인다. 처음에는 문제가 없어보인다.
  
---------------------------------------------------------------------+<​code>​
 ghci> :load BrokenClass ghci> :load BrokenClass
 [1 of 2] Compiling SimpleJSON ​      ( ../​ch05/​SimpleJSON.hs,​ interpreted ) [1 of 2] Compiling SimpleJSON ​      ( ../​ch05/​SimpleJSON.hs,​ interpreted )
 [2 of 2] Compiling BrokenClass ​     ( BrokenClass.hs,​ interpreted ) [2 of 2] Compiling BrokenClass ​     ( BrokenClass.hs,​ interpreted )
 Ok, modules loaded: SimpleJSON, BrokenClass. Ok, modules loaded: SimpleJSON, BrokenClass.
---------------------------------------------------------------------+</​code>​
  
-그러나, ​list-of-pairs ​instance 를 사용하는 순간 문제가 발생한다.+그러나, ​Int 쌍에 대한 ​instance 를 사용하는 순간 문제가 발생한다.
  
---------------------------------------------------------------------+<​code>​
 ghci> toJValue [("​foo","​bar"​)] ghci> toJValue [("​foo","​bar"​)]
  
Line 1050: Line 1065:
     In the expression: toJValue [("​foo",​ "​bar"​)]     In the expression: toJValue [("​foo",​ "​bar"​)]
     In the definition of `it': it = toJValue [("​foo",​ "​bar"​)]     In the definition of `it': it = toJValue [("​foo",​ "​bar"​)]
---------------------------------------------------------------------+</​code>​
  
 위의 overlapping instances 문제는 위의 overlapping instances 문제는
 하스켈이 가진 open world assumption 에 따른 결과이다. 하스켈이 가진 open world assumption 에 따른 결과이다.
-좀 더 명확하게 아래를 보자. 
  
--} +다시 맨처음 나왔던 Borked 타입클래스의 소스를 살펴보자. 
- +<​code>​
- +
----------------------------------------------------------------------+
 -- file: ch06/​Overlap.hs -- file: ch06/​Overlap.hs
 class Borked a where class Borked a where
Line 1072: Line 1084:
 instance (Borked a, Borked b) => Borked (a, b) where instance (Borked a, Borked b) => Borked (a, b) where
     bork (a, b) = ">>"​ ++ bork a ++ " " ++ bork b ++ "<<"​     bork (a, b) = ">>"​ ++ bork a ++ " " ++ bork b ++ "<<"​
---------------------------------------------------------------------- +</​code>​
-{-+
  
-쌍에 대한 ​Borked 의 두가지 ​instance 구현이 있다+페어 ​쌍에 대한 instance 구현은 두개가 ​있다.
-: Int 쌍과, Borked 쌍.+
  
-Int 쌍을 bork 처리려면, +(Int, Int) 와 Borked 타입인 a,b 에 대여 (ab) 이렇게 두개이다.
-컴파일러는 사용한 instance 를 선택해야한다.+
  
-그러나, GHC 는 기본적으로 보수적(conservative) ​며, +문제는 첫번째 instance 인 Borked Int 때문이다.
-오직 가능한 instance 는 한개여야 한다고 여긴다. +
-그래서 위 bork 를 실행하려고 하면 에러가 발생한다.+
  
---------------------------------------------------------+정수쌍 타입에 대해서 두번째 instance (Int, Int) 에도 들어맞고,​ 
 + 
 +Int 는 Borked 타입클래스에 속해있으니,​ 
 + 
 +Borked 타입인 a,b 에 대하여 (a, b) 쌍 이라는 정의에도 성립한다. 
 + 
 +결과적으로 컴파일러가 두 개의 instance 중 어느것에 적용해야 될지 알 수 없어서 에러를 냈다. 
 + 
 + 
 +-----------------------------------------
 -- When do overlapping instances matter? -- When do overlapping instances matter?
 언제 instance 오버랩핑이 중요할까?​ 언제 instance 오버랩핑이 중요할까?​
Line 1093: Line 1109:
 타입클래스의 영향을 받는 메서드를 시도하려고 할때, 타입클래스의 영향을 받는 메서드를 시도하려고 할때,
 어느 instance 를 사용할지 선택을 강요할때 발생한다...????​ 어느 instance 를 사용할지 선택을 강요할때 발생한다...????​
-코드 자체에서 컴파일 에러가 나는 것이 아니라,​ +(->코드 자체에서 컴파일 에러가 나는 것이 아니라,​ 
-  런타임시 애매한 상황에서 선택을 강요받을때 에러가 난다는 말인듯;  +런타임시 애매한 상황에서 선택을 강요받을때 에러가 난다는 말인듯; ​) 
--------------------------------------------------------- +-----------------------------------------
--}+
  
  
Line 1103: Line 1118:
 -------------------------------------------------- --------------------------------------------------
  
-{- 
 보통, 다형성 타입을 위한 특수한 버전에 타입클래스 instance 를 작성할 수 없다. 보통, 다형성 타입을 위한 특수한 버전에 타입클래스 instance 를 작성할 수 없다.
 [Char] 타입은 다형성 타입 [a] 를 Char 타입으로 상세화시킨 것이다. [Char] 타입은 다형성 타입 [a] 를 Char 타입으로 상세화시킨 것이다.
Line 1123: Line 1137:
 -} -}
  
----------------------------------------------------------------------+<​code>​
 -- file: ch06/​SimpleClass.hs -- file: ch06/​SimpleClass.hs
 {-# LANGUAGE TypeSynonymInstances,​ OverlappingInstances #-} {-# LANGUAGE TypeSynonymInstances,​ OverlappingInstances #-}
Line 1140: Line 1154:
 instance Foo String where instance Foo String where
     foo = id     foo = id
---------------------------------------------------------------------- +</​code>​ 
-{-+ 
 +소스 첫줄에 언어확장 주석을 첨부하였기 때문에,​ 
 + 
 +[a] 타입의 instance 가 구현되었고,​
  
-String == [Char] ​< [a]+밑에 좀 더 구체적인 ​[Char](==String) 타입이 오버랩 되서 instance 구현이 되었지만,​ 에러는 안난다.
  
 foo 에 String 을 적용하면,​ foo 에 String 을 적용하면,​
-컴파일러가 String specific(구체적) 구현을 사용하게 될 것이다.+컴파일러가 String specific한 (더 구체적이고 잘맞는) 구현을 사용하게 될 것이다.
  
-심지어 [a] 와 Char 로 foo instance 가 구현되어 있다면 
-String 에 대한 instance 가 더 specific(범위가 좁은거?) 한 것임으로,​ 
-GHC 는 이것을 사용한다. 
-다른 타입의 리스트에 대해서는 [a] 로 선택될 것이다. 
- 
-OverlappingInstances 언어확장을 켜면, 
 GHC 는 같은정도의 specific instance 를 하나이상 발견시 GHC 는 같은정도의 specific instance 를 하나이상 발견시
 코드를 거부(?​)할 것이다. 코드를 거부(?​)할 것이다.
Line 1180: Line 1191:
 그러나, 사용자가 특정 언어 확장을 사용할 필요는 없다. 그러나, 사용자가 특정 언어 확장을 사용할 필요는 없다.
 -------------------------------------------------------------------- --------------------------------------------------------------------
--} 
- 
  
 -------------------------------------- --------------------------------------
 ====== How does show work for strings? ====== ====== How does show work for strings? ======
 -------------------------------------- --------------------------------------
-{- 
  
 show 함수는 string에 어떻게 작동할까?​ show 함수는 string에 어떻게 작동할까?​
Line 1215: Line 1223:
 OverlappingInstances 확장 필요없이도 가능하다. OverlappingInstances 확장 필요없이도 가능하다.
  
--} 
  
  
Line 1222: Line 1229:
 ====== How to give a type a new identity ====== ====== How to give a type a new identity ======
 --------------------------------------------------------------------- ---------------------------------------------------------------------
-{- 
  
-http://​www.haskell.org/​haskellwiki/​Newtype 설명+http://​www.haskell.org/​haskellwiki/​Newtype 설명을 참조하였음.
  
 data 와 newtype 은 거의 똑같다. data 와 newtype 은 거의 똑같다.
Line 1231: Line 1237:
 data 자리에 newtype 을 넣으려면,​ data 자리에 newtype 을 넣으려면,​
 오직 1개의 생성자만 있어야 한다. 오직 1개의 생성자만 있어야 한다.
 +...
  
-... 읽어볼만함 
  
--} +<​code>​
- +
----------------------------------------------------------------------+
 -- file: ch06/​Newtype.hs -- file: ch06/​Newtype.hs
 data DataInt = D Int data DataInt = D Int
Line 1247: Line 1251:
 newtype NewtypeInt = N Int newtype NewtypeInt = N Int
     deriving (Eq, Ord, Show)     deriving (Eq, Ord, Show)
---------------------------------------------------------------------- +</​code>​
-{- +
-newtype 의 목적은 이미 존재하는 타입에 새이름을 지어주는 것이다.+
  
 --------------------------------------------------------------------- ---------------------------------------------------------------------
 -- The type and newtype keywords -- The type and newtype keywords
 비록 이름이 비슷하지만,​ type 과 newtype 키워드는 다른 목적을 가진다. 비록 이름이 비슷하지만,​ type 과 newtype 키워드는 다른 목적을 가진다.
-type 키워드는 타입을 참조하는 또다른 방법을 제공한다. 닉네임 같은. 
  
-우리나 컴파러나 [Char] 와 String 이 같은 ​타입임을 알고 있다.+type 키워드는 ​종의 닉네임같은 ​참조를 제공한다.
  
 이와 반대로, newtype 은 기본 타입을 숨긴다?​!. 이와 반대로, newtype 은 기본 타입을 숨긴다?​!.
 UniqueID 타입을 보자. UniqueID 타입을 보자.
 +<​code>​
 -- file: ch06/​Newtype.hs -- file: ch06/​Newtype.hs
 newtype UniqueID = UniqueID Int newtype UniqueID = UniqueID Int
     deriving (Eq)     deriving (Eq)
 +</​code>​
 컴파일러는 Int 와 UniqueID 를 다른 타입으로 본다. 컴파일러는 Int 와 UniqueID 를 다른 타입으로 본다.
 유저로서는 그것이 Int 로 구현됬음을 알 수 없다. 유저로서는 그것이 Int 로 구현됬음을 알 수 없다.
Line 1277: Line 1278:
 동일성, 정렬, 출력은 Int 의 instance 에서 유도하지만,​ 동일성, 정렬, 출력은 Int 의 instance 에서 유도하지만,​
  
-Int 의 Num or Integer instance 구현은 노출하지 않았기 때문에 해당안된다.+Int 의 Num or Integer instance 구현은 노출하지 않았기 때문에 해당되지 않는다.
  
 +<​code>​
 ghci> N 1 < N 2 ghci> N 1 < N 2
 True True
Line 1290: Line 1292:
     In the expression: N 313 + N 37     In the expression: N 313 + N 37
     In the definition of `it': it = N 313 + N 37     In the definition of `it': it = N 313 + N 37
 +</​code>​
  
- +기존타입에서 일부 성질만을 가져와서 기존과는 다른 identity 를 제공한다고 볼 수 있다.
--} +
  
  
Line 1299: Line 1300:
 ====== Differences between data and newtype declarations ====== ====== Differences between data and newtype declarations ======
 --------------------------------------------------------------------- ---------------------------------------------------------------------
-{- 
  
 data 와 newtype 의 차이점 data 와 newtype 의 차이점
Line 1327: Line 1327:
 undefined 에 관한 패턴매칭시 newtype 과 data 의 결과가 다르다. undefined 에 관한 패턴매칭시 newtype 과 data 의 결과가 다르다.
  
--------------------------------------------------------+<​code>​
 ghci> undefined ghci> undefined
 *** Exception: Prelude.undefined *** Exception: Prelude.undefined
Line 1333: Line 1333:
 ghci> case D undefined of D _ -> 1 ghci> case D undefined of D _ -> 1
 1 1
--------------------------------------------------------+</​code>​
  
 패턴미칭이 생성자를 통해서 이루어짐으로,​ 패턴미칭이 생성자를 통해서 이루어짐으로,​
Line 1339: Line 1339:
 만약 보호되지 않은 undefined 를 바로 사용하면 에러가 발생한다. 만약 보호되지 않은 undefined 를 바로 사용하면 에러가 발생한다.
  
-------------------------------------------------------+<​code>​
 ghci> case undefined of D _ -> 1 ghci> case undefined of D _ -> 1
 *** Exception: Prelude.undefined *** Exception: Prelude.undefined
-------------------------------------------------------+</​code>​
  
 하지만, newtype 의 경우, 하지만, newtype 의 경우,
  
------------------------------------------------------+<​code>​
 ghci> case N undefined of N _ -> 1 ghci> case N undefined of N _ -> 1
 1 1
 ghci> case undefined of N _ -> 1 ghci> case undefined of N _ -> 1
 1 1
------------------------------------------------------+</​code>​
  
 에러가 안났다!!! 에러가 안났다!!!
Line 1357: Line 1357:
  
 실재로 N _ -> 패턴매칭은 _ -> 와 사실상 같다. 실재로 N _ -> 패턴매칭은 _ -> 와 사실상 같다.
 +
 +(이부분은 좀 더... 공부해야 될 거 같네요 -_-; 이해가 잘... newtype 으로 선언한 타입의 경우,
 +
 +실제로 생성자 체크를 런타임에도 하지 않기 때문에 더 효율적이라고 하는거 같은데...흠)
  
  
Line 1362: Line 1366:
 ====== JSON typeclasses without overlapping instances ====== ====== JSON typeclasses without overlapping instances ======
 --------------------------------------------------------------------- ---------------------------------------------------------------------
 +
 +
 +마지막 소챕터... 준비중 ㅜㅜ
study/haskell/ch6.1389622364.txt.gz · Last modified: 2019/02/04 14:26 (external edit)