2015-10-04 2 views
1

У меня есть проблема с функцией, которую я хочу сделать очень полиморфной. Я хотел бы интегрировать функции, аналитически или численно. При аналитическом анализе я предоставляю результат. В числовом случае я хотел бы использовать различные методы, на данный момент, процедуру tanhsinh от tanhsinh. Я также хочу узнать больше о гадцах, поэтому я попытался найти решение, используя их.GADT в полиморфной функции

До сих пор у меня есть следующий:

import qualified Data.VectorSpace as DV 
import Numeric.Integration.TanhSinh 

data IntegrationType a b where 
     MkAnalytic :: (DV.AdditiveGroup b) => (c -> b) -> c -> c -> IntegrationType Analytic b 
     MkNumeric :: NumericType -> IntegrationType Numeric [Result] 

data Analytic = Analytic 
data Numeric = Numeric 
data Method = Trapez | Simpson 
data IntBounds = Closed | NegInfPosInf | ZeroInf 

data NumericType = MkSingleCoreTanhSinh IntBounds Method (Double -> Double) Double Double 
       | MkParallelTanhSinhExplicit IntBounds (Strategy [Double]) Method (Double -> Double) Double Double 
       | MkParallelTanhSinh IntBounds Method (Double -> Double) Double Double 

integrate :: IntegrationType a b -> b 
integrate (MkAnalytic f l h) = f h DV.^-^ f l 
integrate (MkNumeric (MkSingleCoreTanhSinh Closed Trapez f l h)) = trap f l h 
integrate (MkNumeric (MkSingleCoreTanhSinh Closed Simpson f l h)) = simpson f l h 

Этот код компилируется, потому что я expicitly состояние в конструкторе MkNumeric, что переменные б типа

[Result] 

Почему я должен это сделать ? Могу ли я не оставить переменный тип б, как в

data IntegrationType a b where 
    MkNumeric :: NumericType -> IntegrationType Numeric b 

Когда я делаю это я получаю сообщение об ошибке:

Could not deduce (b ~ [Result]) 
from the context (a ~ Numeric) 
    bound by a pattern with constructor 
      MkNumeric :: forall b. NumericType -> IntegrationType Numeric b, 
      in an equation for `integrate' 
    at test-classes-new-programm.hs:139:12-64 
    `b' is a rigid type variable bound by 
     the type signature for integrate :: IntegrationType a b -> b 
     at test-classes-new-programm.hs:137:14 
Relevant bindings include 
    integrate :: IntegrationType a b -> b 
    (bound at test-classes-new-programm.hs:138:1) 
In the expression: trap f l h 
In an equation for `integrate': 
    integrate (MkNumeric (MkSingleCoreTanhSinh Closed Trapez f l h)) 
     = trap f l h 

ответ

3

Тип

integrate :: IntegrationType a b -> b 

говорит, что для любогоa и b по моему выбору, если я позвоню integrate со значением типа IntegrationType a b, я верну значение типа b. При определении

MkNumeric :: NumericType -> IntegrationType Numeric b 

вы позволите, кто применяет конструктор решить, что b есть. Поэтому я мог бы использовать MkNumeric для изготовления значения, например, типа IntegrationType Numeric Int. Но ваш integrate знает, как производить [Result], а не Int.

В рабочего кода, как только integrate «открывает окно доказательств» путем сопоставления MkNumeric, он узнает, что b ~ [Result] и, следовательно, он может вернуть что-то из этого типа.

+0

Хорошо, я могу это понять. Но что, если я хочу не только вернуть «[Результат]», но, возможно, также пару таких результатов, как «([Результат], [Результат])». В принципе, я хочу иметь возможность возвращать набор типов с помощью моей функции «интегрировать». Это то, что, как я думал, было бы возможным, просто произнеся «MkNumeric :: NumericType -> IntegrationType Numeric b' – TheMADMAN

+0

@TheMADMAN, большой вопрос - это то, что вы можете сделать с результатами после их появления. В полностью зависимом от типизации языке вы можете заставить тип результата зависать произвольными способами по входным значениям, но использование результата требует подтверждения того, что он имеет тип, который вам нужен (этот механизм, по-видимому, полезен в основном для вещей в характере метапрограммирования). В Haskell мы не можем этого сделать; тип результата не может зависеть от входного значения. – dfeuer

Смежные вопросы