2013-06-23 2 views
9
take :: Int -> [a] -> [a] 
genericTake :: Integral i => i -> [a] -> [a] 

나는 take의 불편한 유형은 역사적인 이유로 인한 것이며, 그 변경으로 인해 일부 코드가 손상 될 수 있음을 읽었습니다.Integral을 사용하기 위해 테이크 유형을 변경 할 수없는 이유는 무엇입니까?

그러나 takegenericTake으로 대체 할 수 없습니까? 뭐가 문제 야?

+0

나는 타입 추출이'take' 타입에 기반을 둔 상황이있을 것이라고 생각한다.'genericTake'로 "파생 할 수 없다"는 것을 알게된다. – leventov

+4

모호한 경우에 코드 손상에 더하여'take'를'genericTake'로 대체하면 많은 경우에 성능 저하를 초래할 것입니다 (유형 불이행은 이제 'Integer'가됩니다. ':: Int'를 지정하지 않을 때 사용됩니다). – sepp2k

답변

10

genericTake을 위해 휴식하는 파괴의 경우

genericTake :: Integral i => i -> [a] -> [a] 
genericTake n xs = take (fromIntegral n) xs 

class Foo a where 
    bar :: a -> String 

instance Foo Int where 
    bar _ = "int" 

foo :: String -> [a] -> [a] 
foo ns xs = let y = read ns 
       z = bar y 
      in take y xs 

.

No instance for (Foo i0) arising from a use of `bar' 
    The type variable `i0' is ambiguous 

이렇게까지 요리 예입니다하지만 당신은 당신이 Integral i => i으로 유형을 변경하면 현재 몇 가지 문제가 위와 같이 발생할 수 있습니다, Int 있다고 가정 테이크의 첫 번째 인수로 발생하는 어떤 종류의 추론을 이해할 수있다.

+0

+1 이것은 유형 인스턴스의 진짜 고통이며 해결되었습니다. – jpaugh

+0

@jpaugh 수정 제안은 무엇입니까? 고칠 수 있는지 확실하지 않습니다. – Satvik

+0

이것을 시도한 적은 없지만 확장 된 기본 규칙으로 컴파일하지 않습니까? –

관련 문제