Haskell의 암시 적 정적 유형 캐스트 ​​(강제)


9

문제

Haskell의 다음 설계 문제를 고려하십시오. 변수 및 일반 표현식 (다변량 다항식)을 표현하려는 단순하고 상징적 인 EDSL이 x^2 * y + 2*z + 1있습니다. 또한, 나는 표정, 말을 통해 특정 기호 방정식을 표현 할 x^2 + 1 = 1뿐만 아니라 정의 처럼 x := 2*y - 2.

목표는 다음과 같습니다.

  1. 변수와 일반 표현식에 대해 별도의 유형이 있어야합니다. 특정 함수는 복잡한 표현식이 아니라 변수에 적용될 수 있습니다. 예를 들어, 정의 연산자 :=는 유형일 수 있으며 (:=) :: Variable -> Expression -> Definition복잡한 표현식을 왼쪽 매개 변수로 전달할 수 없어야 합니다 ( 명시 적 캐스트없이 변수를 오른쪽 매개 변수로 전달할 수 있어야 함 ) .
  2. Num정수 리터럴을 표현식으로 승격하고 보조 래퍼 연산자를 도입하지 않고 덧셈 또는 곱셈과 같은 일반적인 대수 연산에 편리한 표기법을 사용할 수 있도록 표현식에의 인스턴스를 사용하십시오.

즉, 변수에 대한 암시 적정적 유형 캐스트 ​​(강제)를 표현식에 사용하려고합니다. 이제 Haskell에는 암시 적 유형 캐스트가 없다는 것을 알고 있습니다. 그럼에도 불구하고 특정 객체 지향 프로그래밍 개념 (이 경우 간단한 상속)은 언어 확장 유무에 관계없이 하스켈 유형 시스템에서 표현할 수 있습니다. 간단한 구문을 유지하면서 어떻게 위의 두 가지 사항을 모두 만족시킬 수 있습니까? 가능합니까?

토론

여기서 주요 문제는 Num유형 제한입니다.

(+) :: Num a => a -> a -> a

원칙적으로 변수와 표현식 모두에 대해 단일 (일반화 된) 대수 데이터 유형을 작성할 수 있습니다. 그런 다음 :=왼쪽 식을 식별하고 변수 생성자 만 허용하고 그렇지 않으면 런타임 오류가 발생하는 방식으로 작성할 수 있습니다. 그러나 그것은 깨끗하고 정적 인 (즉 컴파일 타임) 솔루션이 아닙니다 ...

이상적으로는 다음과 같은 간단한 구문을 얻고 싶습니다.

computation = do
  x <- variable
  t <- variable

  t |:=| x^2 - 1
  solve (t |==| 0)

특히, 전체 왼쪽 표현이 아닌 변수의 정의를 제공해야 t + 1 |:=| x^2 - 1하므로 표기법을 금지하고 싶습니다 :=.


1
어쩌면 당신은 class FromVar e메소드 fromVar :: Variable -> e와 함께 and를 사용할 수 Expression있고 Variable, 변수에 다형성 유형 x :: FromVar e => e등 을 가질 수 있습니다 . 나는 지금 휴대 전화를 사용하고 있기 때문에 이것이 얼마나 잘 작동하는지 테스트하지 않았습니다.
Mor A.

FromVartypeclass가 어떻게 도움이 될지 잘 모르겠습니다 . Expr의 인스턴스 를 유지하면서 명시 적 캐스트를 피하고 싶습니다 Num. 달성하고자하는 표기법의 예를 추가하여 질문을 편집했습니다.
Maciej Bendkowski

답변:


8

하위 유형이 아닌 다형성을 활용하려면 (하스켈에있는 모든 것이기 때문에) "변수는 표현식"이라고 생각하지 말고 "변수와 표현식 모두 공통된 작업이 있습니다"라고 생각하지 마십시오. 이러한 작업은 형식 클래스에 넣을 수 있습니다.

class HasVar e where fromVar :: Variable -> e

instance HasVar Variable where fromVar = id
instance HasVar Expression where ...

그런 다음 물건을 주조하는 대신 물건을 다형성으로 만듭니다. 이 있으면 v :: forall e. HasVar e => e식과 변수로 모두 사용할 수 있습니다.

example :: (forall e. HasVar e => e) -> Definition
example v = (v := v)  -- v can be used as both Variable and Expression

 where

  (:=) :: Variable -> Expression -> Definition

아래 코드를 작성하는 해골 : https://gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

computation :: Solver ()
computation = do
  V x <- variable
  V t <- variable
  t |:=| x^2 - 1
  solve (t |==| 0)

흥미 롭습니다, 고마워요! 잠깐 동안 존재 유형 뒤에 변수와 표현식을 숨기는 것을 고려했지만 추가 표기법을 도입했기 때문에 아이디어를 거부했습니다 V. 처음에는 그것이 내가 원하는 것이 아니지만 아마도 그것을 너무 빨리 취소했을 수도 있습니다 ... 아마도 나는 불투명을 제거 할 수 없습니다 V. 관련 메모에서 어떻게 인스턴스를 만들 수 V (forall e . HasVar e => e)있습니까? Coq에서는 유도 형에 대해 유형 계산과 패턴 일치를 사용하지만 Haskell에서이를 달성하는 방법은 확실하지 않습니다.
Maciej Bendkowski

1
당신은 w :: Variable어떻게 든 잡아서 적용 fromVar할 수 있습니다 : variable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable).
Li-yao Xia

1
그리고 Vimpredicative 종류의 피할 수 있지만, 여전히 WIP입니다 수 있습니다. 또는를 variable통해 간접적으로 대신에 다형성 인수로 명시 적으로 계속할 수 있습니다 (>>=).
Li-yao Xia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.