module lc_english /* A toy analysis of the 26 block letters of the English alphabet taught in first grade (at least, when I was in first grade). The task is to describe them in terms of some set of distinctive features, in the same way phonologists describe the sound systems of natural languages in terms of distinctive phonological features. Typographic and/or psychological realism is probably desirable, but is not essential. The immediate goal is to see how whether anything like a plausible analysis is possible and to see whether Alloy can help with some of the bookkeeping. I think the result shows the answer to both questions to be 'yes'. */ open graphemes one sig lc_a, lc_b, lc_c, lc_d, lc_e, lc_f, lc_g, lc_h, lc_i, lc_j, lc_k, lc_l, lc_m, lc_n, lc_o, lc_p, lc_q, lc_r, lc_s, lc_t, lc_u, lc_v, lc_w, lc_x, lc_y, lc_z extends Grapheme {} // lc: is the letter lower-case or not? (Not very distinctive in // this toy example, and you'd probably want uppercase // to be the marked feature, not lowercase, but it's handy // for copy / paste operations. one sig lc extends Feature {}{ sic = lc_a + lc_b + lc_c + lc_d + lc_e + lc_f + lc_g + lc_h + lc_i + lc_j + lc_k + lc_l + lc_m + lc_n + lc_o + lc_p + lc_q + lc_r + lc_s + lc_t + lc_u + lc_v + lc_w + lc_x + lc_y + lc_z non = Grapheme - sic } // asc: does the letter have an ascender or not? // t is a bit of a problem here, but for now we say // it has an ascender. one sig asc extends Feature {}{ sic = lc_b + lc_d + lc_f + lc_h + lc_k + lc_l + lc_t non = Grapheme - sic } // desc: does the letter have a descender or not? one sig desc extends Feature {}{ sic = lc_g + lc_j + lc_p + lc_q + lc_y non = Grapheme - sic } // bowl: does the letter have a round / circular bit or not? one sig bowl extends Feature {}{ sic = lc_a + lc_b + lc_c + lc_d + lc_e + lc_g + lc_h + lc_k + lc_m + lc_n + lc_o + lc_p + lc_q + lc_u + lc_v + lc_w + lc_y non = Grapheme - sic } // Is the bowl (or some other important feature) in the // letter doubled? one sig doubled extends Feature {}{ sic = lc_m + lc_w non = Grapheme - sic } // agape (open is a keyword): if there is a bowl, is it open or incomplete // in some way? one sig agape extends Feature {}{ sic = lc_c + lc_e + lc_h + lc_k + lc_m + lc_n + lc_r + lc_s + lc_u + lc_v + lc_w + lc_x + lc_y + lc_z // s? z? not sure ... non = Grapheme - sic } // post: is there a vertical bar (post) in the letter? // Remember, we are here talking about first-grade // letters, so 'a' is a single-storey letter, consisting of // a bowl (circle) and a vertical line on the right. // And so on. one sig post extends Feature {}{ sic = lc_a + lc_b + lc_d + lc_f + lc_g + lc_h + lc_i + lc_j + lc_k + lc_l + lc_m + lc_n + lc_p + lc_q + lc_r + lc_t + lc_u + lc_y non = Grapheme - sic } // left: if there is a post, is it on the left side of the // bowl? Not sure whether to specify a value for -bowl // letters; shouldn't matter. one sig left extends Feature {}{ sic = lc_b + lc_h + lc_k + lc_m + lc_n + lc_p + lc_r non = Grapheme - sic } // curl: is the post (or other stroke) curled at the end? // Bowed over? one sig curl extends Feature {}{ sic = lc_f + lc_g + lc_j + lc_r + lc_s + lc_y non = Grapheme - sic } // cross: is there a cross-stroke? one sig cross extends Feature {}{ sic = lc_e + lc_f + lc_k + lc_t + lc_x // z? non = Grapheme - sic } // angular: is the letter angular, as opposed to curved? one sig angular extends Feature {}{ sic = lc_k + lc_t + lc_v + lc_x + lc_z non = Grapheme - sic } run show_indistinct run {} check { distinctive[Feature - angular, Grapheme] } // Revision history: // 2010-03-26 : CMSMcQ : made first analysis by adding one // feature at a time and running 'show_indistinct' to find some // set of graphemes not being distinguished, then adding another // feature to distinguish some of them, until the feature set // gave a distinct feature profile to each grapheme. It proved very // handy to evaluate expressions like clump[lc_g,Feature] or // fset[lc_s] in the Evaluator.