Странное сопоставление с образцом с функциями, инстанцирующими Шоу

Таким образом, я пишу программу, которая возвращает процедуру некоторой данной арифметической проблемы, таким образом, я хотел инстанцировать несколько функций для Показа так, чтобы я мог распечатать то же выражение, я оцениваю, когда я тестирую. Проблема состоит в том, что данный код соответствует (-) к первой строке, когда это должно упасть на второе.

{-# OPTIONS_GHC -XFlexibleInstances #-}

instance Show (t -> t-> t) where  
 show (+) = "plus"
 show (-) = "minus"  

main = print [(+),(-)]

возвраты

[plus,plus]

Я просто фиксирую смертную печать греха, функционирует во-первых или там некоторый способ, которым я могу заставить ее соответствовать правильно?

править: Я понимаю, что получаю соблюдающее предупреждение:

Warning: Pattern match(es) are overlapped
         In the definition of `show': show - = ...

Я все еще не знаю, почему это накладывается, или как остановить его.

6
задан 7 October 2012 в 09:55
поделиться

4 ответа

Как сказано в sepp2k и MtnViewMark , вы не можете сопоставить шаблон для значения идентификаторов, только для конструкторов и в некоторых случаи, неявные проверки на равенство. Итак, ваш экземпляр связывает любой аргумент с идентификатором в процессе, скрывающем внешнее определение (+) . К сожалению, это означает, что то, что вы пытаетесь сделать, никогда не сработает.

Типичным решением того, чего вы хотите добиться, является определение алгебраического типа данных «арифметическое выражение» с соответствующим экземпляром show . Обратите внимание, что вы можете сделать свой тип выражения экземпляром Num , с числовыми литералами, заключенными в конструктор «Literal», и операциями типа (+) , возвращающими свои аргументы в сочетании с конструктором для операции. Вот краткий неполный пример:

data Expression a = Literal a
                  | Sum (Expression a) (Expression a)
                  | Product (Expression a) (Expression a)
                  deriving (Eq, Ord, Show)

instance (Num a) => Num (Expression a) where
    x + y = Sum x y
    x * y = Product x y
    fromInteger x = Literal (fromInteger x)

evaluate (Literal x) = x
evaluate (Sum x y) = evaluate x + evaluate y
evaluate (Product x y) = evaluate x * evaluate y

integer :: Integer
integer = (1 + 2) * 3 + 4

expr :: Expression Integer
expr = (1 + 2) * 3 + 4

Попробуем в GHCi:

> integer
13
> evaluate expr
13
> expr
Sum (Product (Sum (Literal 1) (Literal 2)) (Literal 3)) (Literal 4)
9
ответ дан 8 December 2019 в 04:29
поделиться

Решил сам мега хаком.

instance (Num t) => Show (t -> t-> t) where  
show op =
    case (op 6 2) of
        8 -> "plus"
        4 -> "minus"
        12 -> "times"
        3 -> "divided"
1
ответ дан 8 December 2019 в 04:29
поделиться

Вот способ подумать об этом. Подумайте:

answer = 42
magic = 3

specialName :: Int -> String
specialName answer = "the answer to the ultimate question"
specialName magic = "the magic number"
specialName x = "just plain ol' " ++ show x

Вы понимаете, почему это не сработает? ответ в сопоставлении с шаблоном - это переменная, отличная от ответа во внешней области. Поэтому вместо этого вам придется написать это так:

answer = 42
magic = 3

specialName :: Int -> String
specialName x | x == answer = "the answer to the ultimate question"
specialName x | x == magic = "the magic number"
specialName x = "just plain ol' " ++ show x

Фактически, это именно то, что происходит, когда вы пишете константы в шаблоне. То есть:

digitName :: Bool -> String
digitName 0 = "zero"
digitName 1 = "one"
digitName _ = "math is hard"

преобразуется компилятором во что-то эквивалентное:

digitName :: Bool -> String
digitName x | x == 0 = "zero"
digitName x | x == 1 = "one"
digitName _ = "math is hard"

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

instance Show (t -> t-> t) where  
 show f | f == (+) = "plus"
 show f | f == (-) = "minus"

Но для этого потребуется, чтобы функции были сопоставимы для равенства. А это вообще неразрешимая проблема.

Вы можете возразить, что вы просто запрашиваете систему времени выполнения для сравнения указателей функций, но на уровне языка программист Haskell не имеет доступа к указателям.Другими словами, вы не можете управлять ссылками на значения в Haskell (*), только сами значения. Это чистота Haskell, обеспечивающая ссылочную прозрачность.

(*) MVar s и другие подобные объекты в монаде IO - другое дело, но их существование не отменяет сути.

9
ответ дан 8 December 2019 в 04:29
поделиться

Он перекрывается, потому что он обрабатывает (+) просто как переменную, что означает, что на правой стороне страницы идентификатор + будет привязан к функции, которую вы вызвали show.

Невозможно сопоставить с образцом в функциях так, как вы хотите.

6
ответ дан 8 December 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: