Таким образом, я пишу программу, которая возвращает процедуру некоторой данной арифметической проблемы, таким образом, я хотел инстанцировать несколько функций для Показа так, чтобы я мог распечатать то же выражение, я оцениваю, когда я тестирую. Проблема состоит в том, что данный код соответствует (-) к первой строке, когда это должно упасть на второе.
{-# 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 - = ...
Я все еще не знаю, почему это накладывается, или как остановить его.
Как сказано в 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)
Решил сам мега хаком.
instance (Num t) => Show (t -> t-> t) where
show op =
case (op 6 2) of
8 -> "plus"
4 -> "minus"
12 -> "times"
3 -> "divided"
Вот способ подумать об этом. Подумайте:
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
- другое дело, но их существование не отменяет сути.
Он перекрывается, потому что он обрабатывает (+)
просто как переменную, что означает, что на правой стороне страницы идентификатор + будет привязан к функции, которую вы вызвали show.
Невозможно сопоставить с образцом в функциях так, как вы хотите.