2017-02-18 1 views
0

다음은 어리석은 예입니다. 그러나이 문제를 해결하면 다른 문제를 해결할 수 있습니다. 자세한 내용은 in this question입니다.함수 결과 유형에 기반한 최적화

나는이 서명으로 함수를 작성하려면 :

myread :: (Read a) => String -> a 

같은 경우 a ~ Int를 제외하고, myread = read, 그 경우 myread _ = 0인치

분명히이 기능은 어리석은 일이지만, 요점은 반환 유형에 따라 최적화하고 싶습니다.

규칙을 다시 작성하거나 여기에 아무 문제가 없습니다. 실제 문제는 솔루션이 다시 쓰기 규칙 인 경우 발생하지 않는 경우 문제가되지 않지만 적어도 답이 어디에서 발생하는지 예를 들어 설명해주십시오.

+0

올바른 도구를 이미 갖고있는 것처럼 보입니다. 클래스 제약 조건은'a'입니다. 물론'Read Int' 인스턴스는 제어하지 않지만 실제 사용 사례에서는 클래스의 정의와 인스턴스를 제어합니다. 아니면 내가 '최적화'란 뜻을 오해 했나요? (제쳐두고 : 나는'x :: H a => T a'는 "H a"문맥에서 "x"를 의미하지 않기 때문에 다른 해답의 해법이 작동하지 않는다고 생각한다. a => T a "즉, (Read a => F a) -> X''Read a => F a -> X'가 아닌 규칙에 적용됩니다) – user2407038

+0

'Read' 클래스가 있고 이미 존재하는 경우'Int'에 대한 자신의'Read' 인스턴스를 만들 수 없습니다. 어쩌면 내가 너를 오해하고있다. – Clinton

답변

0

결정 불가능한 인스턴스로 새 클래스를 정의하는 방법은 어떻습니까? 당신이 규칙의 왼쪽은 표현 상황에 있음을 기억 경우

{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE UndecidableInstances #-} 

class MyRead a where 
    myread :: String -> a 

instance {-# OVERLAPPABLE #-} Read a => MyRead a where 
    myread = read 

instance MyRead Int where 
    myread = const 0 

main = do 
    print $ (myread "True" :: Bool) -- True 
    print $ (myread "\"string\"" :: String) -- "string" 
    print $ (myread "12" :: Int) -- 0 
+0

이 경우,'MyRead'는 서명'myread :: MyRead a => String -> a'를가집니다. 질문에서 언급했듯이 필요에 따라 서명은'myread :: Read a => String -> a'이어야합니다 (그렇지 않으면 관련 질문에서 문제를 해결하지 못합니다). – Clinton

1

당신은 패턴 맥락에서, (아마도)에, 재 작성 규칙을 직접 하지을 확실한 방법을 이렇게 할 수 있습니다 . 특히 왼쪽에있는 유형 응용 프로그램은 완벽하게 유효합니다. 심지어 유형의 응용 프로그램없이

{-# LANGUAGE TypeApplications #-} 

module A where 

{-# INLINE [1] myread #-} 
{-# RULES "myread" forall s . myread @Int s = 0 #-} 

myread :: Read a => String -> a 
myread = read 

, 다음은 완벽하게 유효합니다 (그러나 출력 유형이 f a했다 당신이, 당신이 .. = (result :: [ _ ])이 없습니다 만 f '최적화'를 원한다면 예를 들어, 일반적으로하지 않을 수 있습니다)

{-# RULES "myread" forall s . myread s = (0 :: Int) #-} 

그리고 예를 들어

module B where 

import A 

fun :: String -> String -> (Int, Bool) 
fun x y = (myread x, myread y) 

규칙이 실행 항상 (물론, 핵심 보는 것을 증거를 사용 생략 무관 비트) :

fun4 :: Int 
fun4 = I# 0# 

fun :: String -> String -> (Int, Bool) 
fun = 
    \ _ (w1 :: String) -> 
    (fun4, 
    case readEither6 (run fun3 w1) of _ { 
     [] -> fun2; 
     : x ds -> 
     case ds of _ { 
      [] -> x; 
      : ipv ipv1 -> fun1 
     } 
    }) 

참고,이 정확히 목표는 무엇인지 정말 의견이 아니라 잘 모르겠어요 이유만으로 대답이지만, 코드는 코멘트를 맞지 않을 것입니다.