2016-03-27 8 views
1
type Foo = { 
    x :: Int, 
    y :: Int 
} 

type Bar = { 
    x :: Int 
} 

foo :: Foo 
foo = {x:1,y:2} 
bar :: Bar 
bar = foo 

не могли соответствовать типЕсть ли способ получить subrecord без unsafeCoerce?

()

с типом

(у :: Int )

Почему это не возможно?

Я не могу использовать

type Bar a = { 
    x :: Int | a 
} 

И не хочу, чтобы воссоздать запись

bar = {x : foo.x} 

ли unsafeCoerce единственный вариант?

В чем может быть проблема с использованием unsafeCoerce?

ответ

3

Если вы хотите, чтобы написать функции сделки с записями, которые только имеют некоторые специфические поля, то вы можете использовать открытую строку вместо:

bar :: forall r. { x :: Int | r } -> { x :: Int | r } 
bar rec = rec 

Это все еще будет совместим с Foo и Bar синонимов.

Однако, если это не хорошо либо, и вы просто хотите, чтобы «забыть» о y тогда unsafeCoerce должно быть хорошо использовать, если вы только когда-либо принуждать Foo к Bar, а не обратно.

я настоятельно рекомендую альясинг unsafeCoerce, а не использовать его непосредственно, хотя:

forget :: Foo -> Bar 
forget = Unsafe.Coerce.unsafeCoerce 

Это легко сделать ошибки при использовании его непосредственно, даже если вы думаете, что вы используете его в принципиальном пути.

Лично я просто делаю новую запись без полей, хотя она включает в себя некоторый шаблон.

+0

Есть ли причина, по которой невозможно использовать 'bar = foo :: Bar', или это просто не реализовано? – ais

+0

Короткий ответ: мы не хотим, чтобы система типов работала именно так. Есть некоторые философские причины, почему, но вот очень конкретный вопрос: если бы вы могли это сделать, тогда вы также могли бы легко исчезнуть из типов типов. –

+0

Но вы уже можете сделать это, создав новую запись '{x: foo.x}'. Поэтому 'a :: B' можно преобразовать в' {x: a.x, y: b.y, ...} '. – ais

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