#debugging #haskell #lambda #case #lambda-calculus
#отладка #haskell #лямбда #случай #лямбда-исчисление
Вопрос:
Я пытаюсь разрешить следующее упражнение Haskell:
Определите функцию exists::(N-> Bool)-> N->Bool
, которая получает предикат p и натуральное число n и возвращает значение True, если между O и n есть какое-либо число, для которого значение p равно true. Примеры:
exists pair three = True
exists isGreaterThanZero O = False
Этот код идет перед моей функцией exists:
{-#LANGUAGE GADTs #-}
{-# OPTIONS_GHC -fno-warn-tabs #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
module Naturales where
import Prelude(Show)
data Bool where { False :: Bool;
True :: Bool
} deriving Show
{- Data Type of Natural Numbers -}
data N where { O :: N ;
S :: N -> N
} deriving Show
zero:: N
zero= O
one:: N
one = S O
two :: N
two = S one
three :: N
three = S two
four :: N
four = S three
...
Вот как я запрограммировал запрошенную функцию с именем exists, но когда я пытаюсь скомпилировать код .hs, он
говорит
exists:: (N->Bool)->N->Bool
exists = p -> x -> case x of {
O -> p O;
(S y) -> if p (S y) then True else existe p y; {- Line 288 -}
}
• Couldn't match expected type ‘GHC.Types.Bool’
with actual type ‘Bool’
NB: ‘Bool’ is defined at EstudiandoRecursion.hs:(9,1)-(11,47)
‘GHC.Types.Bool’
is defined in ‘GHC.Types’ in package ‘ghc-prim-0.5.3’
• In the expression: p (S y)
In the expression: if p (S y) then True else existe p y
In a case alternative:
(S y) -> if p (S y) then True else existe p y
|
288 | (S y) -> if p (S y) then True else existe p y; |
Я полагаю, что логика моей функции существует, она правильная, но, возможно, я допустил синтаксическую ошибку при написании кода.
Комментарии:
1. Похоже, вы определили
Bool
тип в своем коде и, следовательно, больше не ссылаетесь наBool
ofGHC.Types.Bool
.2. @WillemVanOnsem, я обновил описание своего вопроса, добавив свой код заголовка, который находится перед функцией exists
3. Well
if ...
ожидает aBool
встроенного типа, поэтомуTrue
/False
from вашего типа будет недостаточно .
Ответ №1:
Вы переопределили стандартный Bool
тип. Haskell не знает, что ваш собственный переопределенный тип на самом деле совпадает со стандартным, поэтому он рассматривает их как два отдельных типа: Bool
(ваш) и GHC.Types.Bool
(стандартный).
if cond then t else e
Выражение работает только со стандартным Bool
типом, а не с вашим пользовательским. Следовательно, вы не можете использовать его в
if p (S y) then True else exists p y
поскольку p (S y)
возвращает ваш собственный пользовательский Bool
. Вместо этого рассмотрим
case p (S y) of
True -> True
False -> exists p y
который, в отличие if
от, должен работать, выбирая правильные True
конструкторы и False
конструкторы из вашего нового типа. Вы можете использовать case .. of { .. ; ... }
, если предпочитаете фигурные скобки и точки с запятой.
Ответ №2:
Вы используете if … then … else …
выражение. Для этого требуется, чтобы условие имело тип Bool
, и это встроенный Bool
, поэтому определения вашего собственного Bool
типа будет недостаточно.
Однако достаточно работать с case … of …
предложением и, следовательно, сопоставлять шаблоны в ваших True
False
конструкторах / data:
exists:: (N -> Bool) -> N -> Bool
exists = p -> x -> case x of {
O -> p O;
(S y) -> case p (S y) of
True -> True
_ -> exists p y
}