Требовать / ввести контракт в ракетке не удается

Я пытался просмотреть документы, но не могу найти пример, который я мог бы использовать для своего случая. Мне нужно импортировать break из срфи/1.

Вот моя попытка. Пример работает в рэкет #lang.

#lang typed/racket

(require/typed (only-in srfi/1 break)
               ;[break (All (T) (-> (-> T Boolean) (Listof T) (Listof T)))])
               ;[break (All (T) (-> (-> T Boolean) (Values (Listof T) (Listof T))))])
               [break (All (T) (-> (-> String (U False (Listof T))) (Listof T) (Listof T)))])

(define entity-types '("3DFACE"  "3DSOLID"  "ACAD_PROXY_ENTITY" "ARC" "ARCALIGNEDTEXT"  "ATTDEF"  "ATTRIB"  "BODY"  "CIRCLE" "DIMENSION" "ELLIPSE"  "HATCH" "IMAGE"  "INSERT"  "LEADER"  "LINE" "LWPOLYLINE" "MLINE"  "MTEXT"  "OLEFRAME"  "OLE2FRAME"  "POINT" "POLYLINE" "RAY"  "REGION"  "RTEXT"  "SEQEND"  "SHAPE"  "SOLID" "SPLINE" "TEXT"  "TOLERANCE"  "TRACE"  "VERTEX"  "VIEWPORT" "WIPEOUT" "XLINE"))
(define lst '("ENTITIES" "0" "LINE" "5" "BA1C" "330" "1F" "100" "AcDbEntity" "8" "0" "370" "0" "100" "AcDbLine" "10" "253.2926653556182" "20" "1478.621431186484" "30" "0.0" "11" "253.2876653556182" "21" "1478.621431186484" "31" "0.0" "0" "LINE" "5" "BA1D" "330" "1F" "100" "AcDbEntity" "8" "0" "370" "0" "100" "AcDbLine" "10" "253.2876653556182" "20" "1478.621431186484" "30" "0.0" "11" "253.2876653556182" "21" "1476.655431186484" "31" "0.0" "0" "LINE" "5" "BA1E" "330" "1F" "100" "AcDbEntity" "8" "0" "370" "0" "100" "AcDbLine" "10" "253.2926653556182" "20" "1476.655431186484" "30" "0.0" "11" "253.2876653556182" "21" "1476.655431186484" "31" "0.0" "0" "LINE" "5" "BA1F" "330" "1F" "100" "AcDbEntity" "8" "0" "370" "0" "100" "AcDbLine" "10" "253.2926653556182" "20" "1476.655431186484" "30" "0.0" "11"))

(break (lambda ([x : String]) (member x entity-types)) lst)

person KRC    schedule 02.06.2015    source источник


Ответы (2)


Это тип, который я бы присвоил break:

(require/typed
 (only-in srfi/1 break)
 [break (All [T] (-> (T -> Any) (Listof T) 
                     (Values (Listof T) (Listof T))))])

Функция-предикат может возвращать что угодно. Если он возвращает #f, он будет считаться ложным, а любой другой результат будет считаться истинным. Кроме того, как упомянул Согаард, конструктор типа Values необходим, чтобы указать, что break возвращает несколько значений.

Однако на самом деле Racket включает в себя функцию, очень похожую на break, но на самом деле эквивалентную span. Сама функция называется splitf-at, и очень легко реализовать break с точки зрения этой функции, а не использовать srfi/1.

(: break (All [T] (-> (T -> Any) (Listof T) 
                      (Values (Listof T) (Listof T)))))
(define (break pred lst)
  (splitf-at lst (negate pred)))
person Alexis King    schedule 02.06.2015

Это работает для меня:

(require/typed (only-in srfi/1 break)
               [break (All (T) (-> (-> T (U False (Listof T))) (Listof T) 
                                   (values (Listof T) (Listof T))))])

Обратите внимание, что member возвращает либо #f, либо список, первым элементом которого является искомый элемент. Поэтому предикат в примере (lambda ([x : String]) (member x entity-types)) имеет тип (-> T (U False (Listof T))).

Наконец, values необходимо указать, что break возвращает несколько значений.

person soegaard    schedule 02.06.2015